How to roll back after Git error submission

1. Git Architecture

git

  • Workspace:Working area (area modified by current user operation)
  • Index / Stage: Temporary storage area (area after add)
  • Repository: Warehouse area or local warehouse (area after commit)
  • Remote: Remote warehouse (area after push)

Git core concepts

The overall process can be briefly described as:

  • Work area –> add–>Staging area –> commit–>Local warehouse area –> push–>Remote warehouse area
  • Remote warehouse area --> fetch-->Use the corresponding branch file under refs\remotes to record the commit_id at the end of the remote branch and the local warehouse area --> merge-->Work area
  • Remote warehouse area --> pull--> Use the corresponding branch file under refs\remotes to record the commit_id at the end of the remote branch and the local warehouse area and work area

For specific git components and conceptual commands, please move to the following two blogs (hyperlinks):
Git technology dry goods! Git usage practice and a collection of commonly used commands at work!
Git-I don't know how to use git internal implementation mechanism

Create a new Git warehouse. The Git warehouse can be logically divided into three areas-working directory, temporary storage area, and version library. These three areas are abstract. The Git warehouse uses files to record the contents of each area.

Git will track changes to files and content in the working directory. When we create three new files in the working directory of the Git repository, Git will treat the newly created files as changes (the five-pointed star in the figure indicates that the changes have been detected by Git).

We want to submit the html file to the warehouse, first add the changes (new HTML) from the working directory to the staging area. Then submit this file from the staging area to the repository. Only then is a set of snapshots taken, and the committed changes will not be lost.

figure 1

When we modify a file in the working directory, the Git repository will identify the modified part of the file (marked with 2 stars), then we will add the file modification to the staging area, and finally submit the file modification to the repository.

figure 2

Modify the CSS file, add the modification to the staging area, and then submit it to the warehouse.

Question: If we modify a file in the working directory for the first time and add it to the staging area, then we modify the file for the second time, and the second modification is not added to the staging area, and finally we commit the file to the version Library, how many times is the content of the files in the warehouse modified? Please think.

If you modify the CSS file for the first time, add it to the staging area, then modify the CSS file for the second time, and now execute the commit, and only the first modified content will be submitted to the repository.

image 3
When commit is executed, only the content in the temporary storage area will be submitted to the repository.

If we want to commit the second modification to the repository, we must first add the second modification to the staging area, merge the staging of the first modification with the staging of the second modification, and then execute the commit , There will be the first and second modified content in the warehouse.

Figure 4
The content added to the staging area will be merged and submitted to the warehouse together.

The first time you modify the CSS file and add it to the staging area, but the warehouse is not submitted; the second time you modify the CSS file and add it to the staging area, it will be merged with the first modification. At this time, the content submitted to the repository is two The merge of revisions.

2. Practice

Suppose there is such a submission record for the project:

$ git log
commit commit_id4 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800
    第三次修改 README 文件
commit commit_id3 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800
    第二次修改 README 文件
commit commit_id2
Author: test
Date:   Thu Aug 20 16:28:19 2020 +0800
    第一次修改 README 文件
commit commit_id1
Author: test
Date:   Thu Aug 20 16:26:59 2020 +080
    初始化项目

Submit order: commit_id1-> commit_id2-> commit_id3-> commit_id4
Note: gitin each of commithas a commit idcurrent submit unique identification!

Next, let’s solve Xiao Ming’s problem first, and use it git resetto solve it perfectly~

3. Problem solving

Yangzi: Xiaoming, you can use the git reset command to get it perfectly. Let’s take a look at how to solve it.

1. Get the commit id
command of the current submission : git log
get all the commit records under the current project branch;
suppose that the commit id of the above Xiaoming submitted error is commit id:commit_id4this commit;
his last commit is the moment commit id:commit_id3we want to roll back the modification to commit_id3!

Xiaoming: I want to keep the changes I committed just now . The code I modified can't be deleted for me!
Yangzi: No problem

2. Clear the commit before a certain commit id and keep the modified code
Command: In the git reset <commit_id>current scenario: git reset commit_id3
remove all commits after the commit_id is specified, and keep the modified code in the local area, that is Workspace, the middle

Xiaoming: Aha, in this case, I can modify the error code before submitting it; but what about the data that I have pushed to the online warehouse?
Yangzi: Don't worry, there is a way~

3. After modifying the code, add the modified code to the temporary storage area and submit it to the local warehouse.
Command: git add <file_name>and in the git commit
current scenario: git add .and git commitcommit the newly modified code. The commit record after submission is assumed to be as follows:

As you can see, the commit_id4submission record we submitted in error disappeared, replaced by the record we submitted after updating the code commit_id5; this completes the local code modification and update

$ git log
commit commit_id5 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800
    第三次修改 README 文件-更新错误后提交
commit commit_id3 (HEAD -> master)
Author: test
Date:   Thu Aug 20 16:28:45 2020 +0800
    第二次修改 README 文件
commit commit_id2
Author: test
Date:   Thu Aug 20 16:28:19 2020 +0800
    第一次修改 README 文件
commit commit_id1
Author: test
Date:   Thu Aug 20 16:26:59 2020 +080
    初始化项目

The overall process is as follows:

git log
git reset commit_id3
修改代码
git add .
git commit -m '第三次修改 README 文件-更新错误后提交'

Yangzi: Okay, Xiaoming, your problem is solved perfectly.
Xiaoming: Oh, but I have one more question: If I don't want to keep the changes made in the rollback commit , just delete the changes! How to deal with it?
Yangzi: Simple~ Let's take a look at the git reset command as a whole

3.1 Regret medicine git reset

In the following explanation, let's first assume that there is such a commit chain:
commit_id1 --> commit_id2 --> commit_id3 --> commit_id4

git reset <param> commit_id2

resetIt is HEADrepositioned commit_id2on, for commit_id3and commit_id4the current local modifications, for different parameter param, have different treatment:

The reset command has three processing modes:

  • -Soft: keep the commit modification and store the modification in the index; that is to say the area after git add
  • --Mixed: keep the commit modification and store the modification in the local work area; that is, the area before git add
  • -Hard: delete commit modification, use with caution!
  1. git reset --soft
    rolls back all the commits before commit_id without deleting the modifications:
    git reset --soft commit_id
    reset the head, do not move the index, so the effect is that all commit modifications after commit_id put the modifications of id3 and id4 in the index area (temporary storage) Area), which is the area where the file is stored after add, and the local current modification is retained

    git reset --soft SHA will roll back the corresponding commit changes to the staging area:
    soft

  2. git reset --mixed
    all filed before rollback commit_id, without deleting Review: git reset commit_idequivalent to git reset --mixed commit_idthe following git reset --hard commit_ideffects are different.
    Reset the head and index without resetting the work tree. The effect is the modification before commit_id, which is all in the work tree. All the modifications of id3 and id4 are placed in the local workspace for the state that has not yet been added, and the local current modifications are retained .

    git reset --mixed SHA will roll back the corresponding commit changes to the working directory:

    mix

  3. git reset --hard
    rolls back all commits before commit_id and deletes all modifications: git reset --hard commit_id
    reset head, index, work tree, that is, restore the current project status to commit_id status, and delete all the rest (including commit_id after (Submitted and local modifications that have not yet been submitted) Use with caution! !

    git reset --hard SHA will delete the corresponding commit directly and cannot be restored.

    hard

    git reset --hard commit_idThis command is mainly used for code rollback, and is only valid for the code that has been committed to the local. By git reflogprior version id command to view information.

    wohu@ubuntu-dev:~/git_demo/test_demo$ git reflog
    eda37f0 HEAD@{
          
          0}: commit: third commit
    8d2efe6 HEAD@{
          
          1}: commit: second commit
    14b5e12 HEAD@{
          
          2}: commit (initial): first commit
    wohu@ubuntu-dev:~/git_demo/test_demo$ cat README.md 
    - first commit
    - second commit
    - third commit
    wohu@ubuntu-dev:~/git_demo/test_demo$ 
    

    Would like to once again cut back annotation is second committhe next version, you can again by git reset --hard 8d2efe6version of the switch.

    wohu@ubuntu-dev:~/git_demo/test_demo$ git reset --hard 8d2efe6
    HEAD is now at 8d2efe6 second commit
    wohu@ubuntu-dev:~/git_demo/test_demo$ ls
    README.md
    wohu@ubuntu-dev:~/git_demo/test_demo$ cat README.md 
    - first commit
    - second commit
    
    wohu@ubuntu-dev:~/git_demo/test_demo$ 
    

3.2 Regret medicine git revert

Xiao Ming: It turns out that git reset is so powerful! But I still have a problem:

If you want to modify only one commit in the middle without affecting the other commits; it is similar to that we only modify commit_id2 without affecting commit_id3 and commit_id4. What should we do?

Yangzi: (Fortunately I understand so many questions, or I would lose it this time...) Simple! git revert command!

Applicable scenario: During project development, I suddenly found that one of the previous submissions contained a bug; of course, we can make a new modification and then submit it again; however, it is not elegant haha; we can directly rewrite Make a commit with bugs~

Why not just add another commit?
Git revert is used to "reverse" a certain version to achieve the purpose of undoing the modification of that version.
For example, if we commit three versions (version 1, version 2, and version 3), we suddenly find that version 2 is not working (for example, there is a bug). If we want to revoke version 2, but do not want to affect the submission of revoked version 3, we can use The git revert command reverses version two and generates a new version four. In this version four, the things in version three will be retained, but the things in version two have been revoked;

There are two commonly used in the revert command:

  • git revert -e <commit_id>: Redo the submission information of the specified commit
  • git revert -n <commit_id>: Redo the code modification to execute the commit
  1. git revert -e
    redo the commit_id commit information and generate a new new_commit_id
    git revert -e commit_id

  2. git revert -n
    redo commit_id's commit git revert -n commit_id. Modify the commit_id and put it in the index area, we can modify it again and resubmit it

git revert <commitHash>  回退指定提交记录

git revert --no-commit <commitHash> 
回退指定提交记录 --no-commit 不会自动提交成一条 `commit` 后续手动操作

git revert --no-commit <commitHash1> <commitHash2>  
回退多个提交记录

git revert --no-commit <commitHash1>..<commitHashN>
回退一定范围的提交记录,前开后闭(不包含 1,包含 N)

3.3 revert vs reset

  • Git revert uses a new commit to roll back the previous commit, and the commit before this commit will be kept intact;
  • Git reset is to return to a certain commit, the commit and previous commit will be kept, but the modifications after this commit id will be deleted or put back into the workspace to wait for the next commit;

Xiaoming: There is also this kind of operation, you can directly operate a certain commit in the submission process directly! awesome!

4. Regret medicine git checkout

Xiaoming: There is one last question:
What if I find that a file has been modified incorrectly during a development, and I want to restore the file to the state it was in when the code was first pulled ?
Yangzi: Simple! See git checkout to solve this problem!

We know it git checkoutcan be used

  • git checkout <branch_name>Switch branch

  • git checkout -b <branch_bame>Create branches and other operations

It also has the function of rolling back the modification of the specified file . Command: git checkout -- <file_name>
The function of the above statement is to undo all the modification of the local work area of ​​file_name. There are two situations:

  • If file_name has not added this file after commit, it will be revoked to the state in the repository

  • If file_name has added this file after commit, it will be revoked to the state of the temporary storage area, which is the state after add

In short, it is to make the specified file is rolled back to a recent git addor git commitstate of!

git checkout --fileThis command is to revoke the code that has not been submitted to the cache area. Create an empty file Readme.md. By git statusstate view the files in the workspace.

wohu@ubuntu-dev:~/git_demo/test_demo$ echo "hello world" >> Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   Readme.md

no changes added to commit (use "git add" and/or "git commit -a")
wohu@ubuntu-dev:~/git_demo/test_demo$ 

Then execute git checkout -- Readme.md. We reverted to the previous version.

wohu@ubuntu-dev:~/git_demo/test_demo$ cat Readme.md 
hello world
wohu@ubuntu-dev:~/git_demo/test_demo$ git checkout -- Readme.md
wohu@ubuntu-dev:~/git_demo/test_demo$ cat Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ 

We edit the content of the Readme again and put it in the cache.

wohu@ubuntu-dev:~/git_demo/test_demo$ echo "hello world" >> Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ git add Readme.md 
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   Readme.md

wohu@ubuntu-dev:~/git_demo/test_demo$ git checkout -- Readme.md
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   Readme.md

wohu@ubuntu-dev:~/git_demo/test_demo$ 

At this point execution git checkoutis not what effect, if you want to use the command will restore our next article.

git reset HEAD -- file This command cancels the code placed in the temporary storage area and puts it in the work area.

wohu@ubuntu-dev:~/git_demo/test_demo$ git reset HEAD -- Readme.md
Unstaged changes after reset:
M	Readme.md
wohu@ubuntu-dev:~/git_demo/test_demo$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   Readme.md

no changes added to commit (use "git add" and/or "git commit -a")
wohu@ubuntu-dev:~/git_demo/test_demo$ 

In this way, our Readme.md code is back to the workspace again. Again git checkoutto restore the contents of the code.

Reference:
https://gitbook.cn/books/5f4db870237b0e7d7f238fa0/index.html
https://gitbook.cn/books/5ebca21b9b907c12334b6287/index.html

Guess you like

Origin blog.csdn.net/wohu1104/article/details/114645119