Git notes (ii)--[diff, reset]

Source: Internet
Author: User
Tags commit comparison diff hash using git sourcetree
The book is connected to the last, straight into the subject. If you're on the next page, run git reset HEAD test.txt and git checkout test.txt to discard the current changes and get the latest commit back to "commit temp", run git status and see " Nothing to commit, working directory clean ". Here, "nothing to commit" indicates that the staging directory is empty, and "working directory Clean" indicates that your working directory has not been modified.

Back to this state is to facilitate our following explanation, at this time the Sourcetree State is: diff-Come, uncle to you check the body

A good diff command reminds me of this wretched classic line, and diff allows you to compare any of the two states in a project. When it comes to comparisons, nature has source and target, so the most intuitive usage of the diff command is actually git diff source target. Here the source and target are similar to those in checkout, which can be "commit hash", "branch Name", "Shortcut". For example, we want to compare the first two commits in Figure 13, run git diff ce81811 6382c7d, and get the results as shown below:

As you can see, the result of the comparison is actually based on the target, that is, the target compared to the source changes, the result of Figure 15 commits "6382c7d" than "ce81811" less than three lines, a line, respectively, with a minus sign and Gash. Similarly, the result of using Git diff master branch2 and git diff HEAD Branch2 is consistent with the above, and the branch name and the "HEAD" category can be seen as a shortcut to commit.

This source and target are the easiest to understand, and the complexity is complicated if we omit a parameter. For example, running Git diff branch2 results as shown in the following figure:

As you can see, the result of Figure 16 is the opposite of Figure 15. That is, Git diff branch2 is the same as Git diff branch2 Head, that is, if you give only one parameter, this is the latest commit that source,target defaults to the current branch. Now that's the right conclusion. Note that we are now in the "Scratch directory is empty" + "working directory Clean" situation, now we make the working directory dirty try, give test.txt add a line "Test 6" and save. Then try git diff branch2, as shown in Figure 17:

You can see that the new "Test 6" is also in. It can be concluded that, in the case of the working directory is not clean, target is the default representation of the working directory. It's still too early to see if there's anything going on in the staging directory. Running git add test.txt, and then continuing with Git diff branch2, found that the results are consistent with Figure 17, which still doesn't explain the problem because the working directory is consistent with the staging directory (both to test 6). Then we add a line "Test 7", when the working directory is "Test 7", the staging directory or "Test 6", at this time running git diff branch2, found "Test 7" This line has also been added. At this point we can basically conclude that target is actually working directory by default.

In front of the case of omitting a parameter, the two parameters are omitted how to do it. Running git diff results in the following diagram:

You can see that the comparison result is only added "Test 7", so the source at this time is the staging directory, and Target is the working directory. To verify this, we run git add test.txt, add the "Test 7" to the staging directory, run Git diff and return the result empty, because the staging directory and working directory are consistent. We do a commit git commit-m "commit 6,7", at this time, the staging directory is empty, working directory clean, continue to run Git diff, or empty. Here we can conclude that if two parameters are omitted, the default source is the staging directory, and the default target is the working directory.

The previous situation involves "comparison between commits", "comparison of each commit and working directory", "staging directory vs. working directory", then only one case, I would like to compare "staging directory" and "each commit" how the whole. To achieve this, let's start by giving the staging directory something: Add a line of "Test 8" and save it, then git add test.txt, and then add a line "Test 9" to the edit test.txt, because staging area has something and staging area is different from the working directory. When running git diff--cached Branch2, you can see the result as follows:

You can see that "Test 8" is in the picture and "Test 9" is not there, indicating that the target has become staging area at this point.

Summarize the various scenarios of diff: The result of git diff source Target is the change of target relative to source, where source and target can be a commit hash/branch name/shortcut if you give only one argument, This parameter is the source, and the default target is the working directory, if the working directory clean, then target is the current branch of the latest commit if a parameter is not given, the default source is the staging directory, and Target is the working directory If you want to have the staging directory as target, you need to use the--cached parameter

Before moving on, commit all the changes you have just made, running git add test.txt and git commit-m "commit 8,9". Reset-You can do whatever you want with me.

The biggest benefit of version control is that it is easy to find the previous version and restore it, so the position of the Reset command is important from this point of view, allowing you to arbitrarily ravage the entire project. When it comes to recovery, there is also the concept of source and target, where the source is definitely the individual commits (including the branch name and shortcut), and target may be the staging directory or working directory or both as target depending on the parameters. For example, we select the parent commit of the current commit as source, run git reset head~ test.txt, prompting for unstaged change, at this time Sourcetree uncommitted The status of the changes is shown below:

As you can see from Figure 20, the file state of the staging area is consistent with the parent commit, and the change is to subtract the two lines of "Test 8" and "Test 9", indicating that the working directory has not changed (the working directory contains both lines). You can see that the target in this case is actually a staging directory, and it does not change the working directory. In this case, we will make up for the lessons owed earlier, and remember that we used git reset HEAD in front of the git add anti-operation. Test.txt, in fact, is also the head state of the file restored to the staging area, the working directory remains the same, and then the latest commit file state and working directory is consistent, so the final effect is "git add anti-operation." In fact, the head can also be omitted, because the default source is the current branch of the latest commit. Further, the filename test.txt can also be omitted, the default will be all the files in the repo recovery, because at this time we have only this one file, so the effect is the same.

Before we introduce the other reset parameters, we want to reset the reset again, which is simple, just run git reset again, because what we need is "git add anti-operation". Then add the parameters to run Reset,git reset--soft head~, note here we do not omit the file name, but once added the--soft will not be able to follow the path, but the entire project to recover all the files, the result is as follows:

As can be seen, this reset directly changed the head, the original "Commit 8,9" disappeared, the latest commit into the original head~, but this time reset still did not modify the working directory, but the "commit 8,9" file status add to the staging area. Since there are--soft parameters, there will certainly be--hard parameters, this time we maintain the current state, directly run git reset--hard ce81811 (commit temp corresponding hash), found that the current latest commit into "commit temp And the staging area is empty, and then the working directory is clean, stating that the--hard parameter restores the working directory to the state of "commit temp" and empties the staging area, regardless of the state before the command was run. This is also more in line with--hard the word tough meaning. The Sourcetree state diagram at this time is:

As you can see from the diagram, Commit temp has been lost and the entire project is forcibly restored to the state where commit temp is.

Summarize the usage of reset: git reset [commit hash/Branch name/shortcut] [filename] similar to "git add anti-operation", directly restores the file state of the commit to the staging area. Omitting commit defaults to head, and omitting the file name defaults to all files. Changes the staging directory only, does not change the working directory, the current commit does not change. git reset--soft [commit hash/Branch name/shortcut] Soft recovery, restore the previous commit file state to staging area, the latest commit is the commit in the parameter. Only change the staging directory, not change the working directory, the current commit changes. git reset--hard [commit hash/Branch name/shortcut] Hard recovery, forcing the entire project to revert to the file status of a commit in the parameter, emptying the staging directory, working directory clean. The staging directory and working directory are changed at the same time, and the current commit changes.

Additional additions to the Reset command: The current head is already in "commit temp" and is not found in the previous commit. Of course not, Reset's operation can also be reset. There are two ways: if you remember the hash of "commit 8,9" (as you can see from Figure 20), then direct git reset--hard 1a222c3, the project will be forced back to the state where commit 8,9 is. If you don't remember, run git reflog and this command will output a list of all the changes that have occurred at the head. The following figure:

In Figure 23 can be found that "commit 8,9" the corresponding entry is 1A222C3 head@{9}: Commit:commit 8, 9, the first is a commit hash, the second is naturally a shortcut. So as long as we run git reset--hard head@{9}. Note that my reflog output may be different from yours, because I may have done a lot of extra work to write tutorials.

P.s. Obviously two is not enough Ah, found that the main Retina screen of the Intercept Tutanima big ... Let's talk about the rest of the next article.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.