1. Git Architecture
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)
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.
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.
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.
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.
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: git
in each of commit
has a commit id
current submit unique identification!
Next, let’s solve Xiao Ming’s problem first, and use it git reset
to 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_id4
this commit;
his last commit is the moment commit id:commit_id3
we 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 commit
commit the newly modified code. The commit record after submission is assumed to be as follows:
As you can see, the commit_id4
submission 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
reset
It is HEAD
repositioned commit_id2
on, for commit_id3
and commit_id4
the 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!
-
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 retainedgit reset --soft SHA will roll back the corresponding commit changes to the staging area:
-
git reset --mixed
all filed before rollback commit_id, without deleting Review:git reset commit_id
equivalent togit reset --mixed commit_id
the followinggit reset --hard commit_id
effects 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:
-
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.
git reset --hard commit_id
This command is mainly used for code rollback, and is only valid for the code that has been committed to the local. Bygit reflog
prior 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 commit
the next version, you can again bygit reset --hard 8d2efe6
version 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 commitgit revert -n <commit_id>
: Redo the code modification to execute the commit
-
git revert -e
redo the commit_id commit information and generate a new new_commit_id
git revert -e commit_id
-
git revert -n
redo commit_id's commitgit 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 checkout
can 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 add
or git commit
state of!
git checkout --file
This command is to revoke the code that has not been submitted to the cache area. Create an empty file Readme.md. By git status
state 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 checkout
is 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 checkout
to restore the contents of the code.
Reference:
https://gitbook.cn/books/5f4db870237b0e7d7f238fa0/index.html
https://gitbook.cn/books/5ebca21b9b907c12334b6287/index.html