preface

Git as a version control tool, its core function is version rollback, no one. Getting familiar with git version rollback will give you the freedom to develop without the fear of accidentally deleting files you shouldn’t have. In addition to version rollback, this section also introduces the use of Stash.

1. Version Rollback

In Git, you can always go back to a certain point in the repository. This is called version rollback.

As shown in the figure above, the current master branch pointer points to D. You can use version rollback to make master point to C, B, or A. There are basically three types of commands for rollback: reset, revert, and checkout. Let’s explain them one by one:

Ⅰ.git reset

1. The parameters

The reset command can add many parameters, including –mixed, –soft, and –hard. Here are the four phases of a complete commit:

The three parameters are generally different as follows:

  • --mixed: is the default valuegit reset. The rollback function is used to roll back a file toThe workspace, will be retainedThe workspaceFile, but will be discardedThe staging areaFile in;
  • --soft: Rolls back a file toThe staging area, will be retainedThe workspaceandThe staging areaFile in;
  • --hard: Rolls back a file toBefore the changeIs discardedThe workspaceandThe staging areaFile in;

Here’s how to use them in detail:

First, make four commits on the master branch. Each commit adds a line of text to test.txt:

--mixed

This parameter is the default value and can be used to roll back the file to the workspace: Roll back the test. TXT file to commit as shown in the following figure:

You can see that the changes made to test. TXT in the fourth commit are rolled back to the workspace, and the changes made to test. TXT in the fourth commit are retained. Therefore, the contents of the test. TXT file in the workspace are the same as before the rollback.

--soft

This parameter rolls back the test. TXT file to the staging area, as shown in the following figure.

You can see that the fourth commit’s changes to test.txt are rolled back into the staging area, and the workspace and the changes made to test.txt in the staging area are retained, so the contents of the files in the workspace are the same as before the rollback.

--hard

This parameter is used to roll back the test. TXT file to its original state, as shown in the following figure:

You can see that test.txt goes straight back to the fourth commit, at which point the changes made to test.txt by the fourth commit in the workspace and staging area are deleted. So, the workspace is clean, and the contents of the test.txt file revert back to when the third commit was completed.

2. Writing

To illustrate the various uses of reset, the following commands take the –hard parameter.

git reset --hard HEAD^

This command rolls back a commit:

The rollback state is as follows:

As you can see, this method changes both the HEAD and master Pointers;

git reset --hard HEAD^^

This command rolls back two commits:

The rollback state is as follows:

Again, with the –hard parameter for rollback, the workspace is clean; As you can see, this method also changes the HEAD and master Pointers;

git reset --hard HEAD~n

This command is used to roll backnTime to submit:

As you can see, with the –hard parameter, the rollback results are as expected, and the method also synchronously changes the HEAD and branch master Pointers.

Note: In this mode, you can only roll back forward, but not backward.

HEAD can be replaced with a branch name, such as master:

git reset --hard master~n
Copy the code

This command rolls back the master branch n times. Since HEAD always points to the current branch, using the branch name has the same effect as using HEAD.

git reset --hard commit_id

This directive backs back to the commit version of the specified COMMIT ID. Since the COMMIT ID is not duplicated, it is generally recognized by writing only the first few (6) bits. The commit ID can be used to roll back either forward or backward. ** Back from 1st commit to 4th commit where commit ID = bdb373… .

To familiarize ourselves with this directive, we can rollback in two ways: using the –hard parameter and using the default parameter.

  • use--hardparameter

    As you can see from the figure, commit_id: BDB373 is smoothly backed back from the first commit to the fourth commit with a clean workspace. This method also modifies the direction of HEAD and branch master as follows:

  • Use default parameters

    You can see that the 4th commit is switched back, but the test.txt file in the workspace remains unchanged; This is because 2nd line, 3rd line, 4th line need to be deleted from test. TXT file in workspace during 4th -> 1st. With the default parameter –mixed, the files modified by 4th Commit are reverted to the workspace, as shown below:

    This procedure discards file deletions in the staging area, but preserves file deletions in the workspace. So, the test.txt file in the workspace is still in the state with three lines deleted.

    In this case, you only need to move the modification from Phase 1 to phase 0 to restore the file to the original state and clear the workspace. Git restore test.txt

Ⅱ.git revert

Revert REVERT revert revert revert revert Unlike reset, which does version rollback by changing branch orientation directly and does not produce new commits; Revert allows version rollback by creating an additional commit to cancel a specific commit on the branch. As shown in the figure below, if you want to redo commit B, the state before and after the redo is:

By redo Commit B, we mean that everything done in commit B is undone in the new commit B’. In other words, the idea behind revert is to undo an unwanted commit by creating a new one. Therefore, the number of submissions will increase.

1. The parameters

Git also provides a number of parameters for Revert, of which three are commonly used. To demonstrate what they can do, we first need to set up the corresponding test environment: make four commits on the dev branch, each one adding a line to test.txt:

-e

The -e parameter is short for –edit and is the default git Revert parameter. Git Revert -e is the same as Git Revert. This parameter edits the commit information while creating a new commit during the redo process. For example, redo the dev2 commit above with the following command:

git revert f4a95
Copy the code

Executing this directive creates a new commit to cancel the commitdev2Everything you do, and it goes intovimEditor to edit a newly submitted submission comment:

As shown below, the dev2 text added to the test.txt file by committing dev2 is cancelled and there is an additional commit on the dev branch:

--no-edit

This parameter does not edit comments that are newly submitted due to revert. As shown below, through:

git revert --no-edit f4a95b
Copy the code

To Revert a dev2 submission, you do not go to the Vim editor to edit the newly submitted comment. Instead, you use the default comment: “dev2” :

-n

The -n parameter is short for –no-commit. It allows you to revert any changes you make to a particular commit.

As you can see in the following figure, the revert directive undoes a new commit B by creating a new commit B’. There are 0 to 4 stages. Without the -n parameter, the Revert directive produces an additional commit B’, which is stage 3 in the figure below. With the -n parameter, the Revert directive also reworks commit B by creating a new commit B’. However, we are still in the process of generating commit B’ and have not yet fully generated commit B’, which is phase 2 in the figure below.

This has the advantage of allowing us to interfere with the revert process and manually commit. As shown below, through:

git revert -n f4a95
Copy the code

The redo process was manually paused during the dev2 commit. Although the changes to test.txt made by committing dev2 have been undone, the redo operation has not yet committed:

This allows us to either fix the areas we don’t like during the redo, or add comments at will. After the modification is complete, the REVERTING operation can be completed by manual submission:

2. Writing

There are several ways to write the revert directive, and the following are the main ones. For the sake of demonstration, the following commands use the default parameter -e to manually edit the comment information for each new submission.

git revert commit_id

This is the most common way of writing, where commit_id is used to select exactly which commit you want to redo. There are two cases:

  • ** Case one: ** redo the last commit without conflict.

    For example, redo the most recent commit dev2 on the dev branch with the following command:

    git revert f4a95b
    Copy the code

    First enter vim editor to edit the newly submitted comment information:

    Then complete the redo operation, as shown below; Dev2 = test.txt; dev2 = test.txt; dev2 = test.txt;

  • ** Case 2: ** reworks a non-latest commit, causing a conflict.

    For example, redo the third commit dev1 on the dev branch with the following command:

    git revert dbde45
    Copy the code

    Merge conflicts occur:

    Use git mergetool to display the conflicted test.txt file using the vim editor tool vimdiff:

    Press Enter to enter the Vim editor interface to resolve the conflict:

    After resolving the conflict, make a manual commit to complete the Revert process:

  • Why the conflict?

    As you can see from the above example, the new commit generated by the revert operation is actually a combination of two commits. As shown below:

    • First, the submission will be redonedev1The previous submission of2ndI’m going to make a copy of that2nd';
    • Then, combine it with the latest commit of the current branchdev2To generaterevertOperation added commit;

    Given the origin of the new commit for the REVERT operation, it’s easy to see why merge conflicts occur, as shown in the following figure:

    The contents of the test.txt file are different in the two commits of the merge. Git does not know which version to use, which will naturally lead to automatic merge failure, you need to manually merge.

git revert HEAD

This directive rewrites the last commit of the branch without conflict:

git revert HEAD^

This command is used to redo the penultimate commit of the branch, which will cause a collision and require manual merging to complete the redo operation:

git revert HEAD^^

The third to last commit of the branch where the redo operation is performed will cause a collision and require manual merging:

git revert HEAD~n

This command is used to redo the n+1 commit of the branch to which it belongs, which will cause a conflict and require manual merge to complete the redo operation. The process is the same as above and will not be repeated here.

Git revert Commit_id git revert Commit_id

3. Cancelrevertoperation

The simple idea is to undo the previous revert operation with the revert operation.

Before the operation, the commit record and test. TXT file on the dev branch are as follows:

Git revert –no-edit f4a95 rework dev2 with git revert –no-edit

After the redo, there was an extra commit and the dev2 line was removed from the test.txt file. In this case, you can use:

git revert --no-edit 582d127
Copy the code

To undo a previous redo by redoing it:

As you can see above, despite the extra commit, the dev2 content that was deleted from the test.txt file is restored, which undoes the revert operation.

Ⅲ.git checkout

1.git checkout commit_id

Using checkout allows you to do version rollback, such as using:

git checkout cb214 
Copy the code

Back to submit 3rd, the following message is displayed:

Note that the HEAD is no longer pointing to the master branch, but to cb214… For the third commit, view the historical commit record:

You can see that there are only 3 submissions, so what does that mean? As shown below:

Git checkout lets the HEAD pointer point to commit 3, which you can think of as a new branch. However, the branch is not actually created, so the chain of commit objects that head points to from commit 1 to commit 3 is free.

Next, make a new change to the file with the HEAD still pointing to the free commit node 3:

  • Now if we switch backmasterBranch, the following error occurs

If you switch from a free commit to the master branch without saving, the change will be overridden by the checkout command. We can do a commit before switching:

The current state is:

  • In a freeCommitAfter making a commit in the object chain, pass again:git checkout masterSwitch to themasterBranches:

If there are no branches pointing to the Commit that was just made in the stray Commit object chain, the Commit will be ignored. At this point, the state is shown in the figure below:

If you want to create a branch that holds (points to) the chain of stray Commit objects, now would be a good time. Follow the instructions above:

git branch mycommit  c4d5cc3
Copy the code

Create branch myCOMMIT to commit commit_id C4D5CC3 (commit node 5 above) :

The resulting free chain of Commit objects is pointed to by the new branch and saved, as shown below:

Conclusion:

  • throughcheckoutThe version rollback will result in a separate chain of submitted objects, and an additional branch needs to be created for saving.
  • Therefore, usecheckoutTo roll back the version, switch to the submitted version that you want to roll back, and then delete the branch that you want to roll backdev. Finally, create a new onedevThe branch points to a stray chain of commit objects, completing the branchdevVersion rollback, referred to as “The Day”;
  • As long as the branch points to it, the commit is not discarded.

Ⅳ.revertwithresetThe choice of

Since checkout creates a loose chain of submitted objects, it is common to use reset and revert instead of checkout:

  • revertUndo an action by creating a new commit. Commit records before and after the action are retained and the undo action is treated as the latest commit.
  • resetBy changingHEADCommit records after this operation are not retained and no new commit is created.

For personal development, reset is recommended. However, it is recommended to use Revert in team development, especially for public branches (such as Master), so that a complete commit history can be retained and easily traceable.

ⅴ. Rollback methods summary

There are three main rollback methods: reset, Revert, and checkout.

methods The effect Forward and back Back to back Synchronous changeHEADAnd branch pointing
git reset --hard HEAD^ Go back1Time to submit can no is
git reset --hard HEAD^^ Go back2Time to submit can no is
git reset --hard HEAD~n Go backnTime to submit can no is
git reset --hard <commit_id> Fall back to the specifiedcommit idThe submission of can can is
git revert HEAD Redo the latest commit can no is
git revert HEAD^ Redo the penultimate commit can no is
git revert HEAD^^ Redo the third to last commit can no is
git revert HEAD~n Redo the reciprocaln+1Time to submit can no is
git revert commit_id Redo the specifiedcommit_idThe submission of can can is
git checkout commit_id Fall back to the specifiedcommit idThe submission of can can no

As you can see from the table above, there are only three ways to go back and forth freely:

git reset --hard commit_id
git revert commit_id
git checkout commit_id
Copy the code

However, a rollback using checkout involves a stray commit that requires you to create a new branch to save, so it’s not often used.

Second,git stash

1.git stashThe role of

The Git Stash directive is used to save loose changes that are not committed to the repository but are located in a workspace or staging area and can be recovered if needed. Specific application scenarios are as follows:

Commit twice on the Master branch: 1st and 2nd, then create and switch to the dev branch. A commit (dev1) is made on the dev branch where both branches are in the following state:

Add dev2 to test. TXT file on dev branch, add dev2 to test. TXT file on dev branch

Changes made on the dev branch are overwritten by the checkout operation. Let’s see if the same problem occurs when we add this change to the staging area on the dev branch and then switch branches:

You can see that the error still occurs, which is a preliminary validation of the conclusion that changes in the workspace and staging are overwritten by the checkout operation. The reasons are as follows:

Although the file was modified on the dev branch, this modification was not committed. There are no commit nodes, as shown in the figure above. Modifying Dev2 is free and discarded when switching branches.

This is a common situation in daily development, where while developing new functionality on the Develop branch, the Master branch has an emergency and needs to switch back to fix it. However, the new functions of the current branch have not been completely developed, and if you switch branches hastily, the content of the original development will be covered and lost, how to do?

One might say that a commit is enough. You can. However, this does not meet the principle that submitted code is correct code. A better solution is to use git Stash, as shown below:

The git-stash stash stash allows you to save changes on the current dev branch that are in the workspace or staging area without committing them. After saving, you can smoothly switch back to the master branch.

WIP (Working in Progress) in the figure represents the workin progress.

When we have finished working on the master branch and switched back to the dev branch again, look at the test.txt file:

The changes dev2 made before the branch switch disappeared. Why?

  • In fact, the changes in the workspace or staging area on the dev branch are committed to the Stash area through git Stash, and the dev branch is rolled back to its original state. As shown below:

  • Changes on the test branch will still be overwritten when you switch to the Master branch. So, when you go back to the Dev branch again, you need to recover the changes saved before switching the branch from the Stash area;

How do you restore the changes saved to stash through git Stash? It can be done through:

git stash list
Copy the code

Look at the stash saved changes on the branch:

Continue to add the contents to the test.txt file: dev3 and add a comment while saving the changes with the following command:

git stash save 'comments'
Copy the code

  • First, you can modify it by using the above commandstashStores the modified remarks.
  • Secondly, although intestChanges are made twice on the branch, but usegit stashSave the modification after the filetest.txtIt’s not actually modified;

2. RestorestashStorage modification

There are many methods, mainly including the following three:

git stash pop

As shown in the figure, the most recent change stored in Stash is restored with the command above. As you can see, stash is very similar to stack: the changes saved first are ranked last and have the largest number; After saving the modification, ranked first, the smallest serial number;

After restoring the most recent change, look again at stash:

You can see that there is only one change left in the store.

  • ** First: ** recoverystashThe last modification stored in
  • ** Second: ** changes this modification fromstashRemove the;
git stash apply

As shown in the figure above, a merge conflict occurs when using this directive. This is because every change saved in Stash represents a version.

  • As the picture above shows, intestOn the branch, after the first change, passgit stashTreat the change as a change0Save tostash, the files in the branch have not changed;
  • The second change is passedgit stashTreat a change as a change1Save tostashThe files in the branch remain unchanged. At this timestashIs equivalent to saving two modified versions on the same branch;
  • Pass ** at this pointgit stash popTake out the modification0, andtestBranch to merge; throughgit stash pop** Remove and modify1And, again,testBranches are merged, and two versions are merged, which naturally causes conflicts.

After manual conflict resolution, a commit is required to complete the manual merge; Then look at Stash:

Change 0 still exists, indicating that the **git stash apply** is used to extract the latest (previous) stash change and merge it with the branch. However, this change stored in stash is not deleted;

git stash apply stash@{n}

This is the most common method to restore a particular change from stash without deleting it from stash.

Store the two changes to test.txt into stash via git Stash as shown below:

Restore stash change 1 with git stash apply stash@{1} :

As shown in the figure above, stash Change 1 is successfully restored and stash Change 1 is not deleted;

Conclusion:

  • git stash pop: Restores and deletesstashThe latest changes to the storage in;
  • git stash apply: Restores but does not deletestashThe latest changes to the storage in;
  • git stash apply stash@{0}: Restores but does not deletestashSpecific commits stored in;