Git Tools - View Revisions
Git has many ways to specify a single commit, a group of commits, or a range of commits.Knowing them is not required, but it never hurts.
Revision refers to: Submit
single revision
You can specify it by the full 40-character SHA-1 hash of any submission, but there are many more user-friendly ways to do the same thing.This section will introduce various methods of obtaining individual commits.
Short SHA-1
Git is very smart. You only need to provide the first few characters of SHA-1 to get the corresponding commit. Of course, the number of SHA-1 characters you provide No less than 4 , and there is no ambiguity - that is, no other object in the current object database starts with this SHA-1.
For example, to view a commit that you know has a feature added, first run the git log command to locate the commit:
$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
added some blame and merge stuffView commits for a given SHA-1 value
In this example, assuming that the SHA-1 of the commit you want starts with 1c002dd...., then you can use the following variations of git show to view the commit (assuming the short version is unambiguous):
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002dGit can generate short and unique abbreviations for SHA-1 values.If you add the --abbrev-commit parameter after git log, a short and unique value will be displayed in the output result; the default is seven characters, but sometimes the number of characters is increased to avoid SHA-1 ambiguity:
$ git log --abbrev-commit --pretty=oneline
ca82a6d changed the version number
085bb3b removed unnecessary test code
a11bef0 first commitUsually 8 to 10 characters are enough to avoid SHA-1 ambiguity in a project.For example, as of February 2019, the Linux kernel, a fairly large Git project, has more than 875,000 commits in its object database, containing seven million objects, and only needs the first 12 characters to ensure uniqueness.
| Note | A brief note on SHA-1 Many people feel that it is possible to have two different objects in their repository with the same SHA-1 value.Then what?If you do commit an object to the repository that has the same SHA-1 value as a previous different object, Git will find that the object's hash value already exists in the repository, think that the object has been written, and use it directly.If you want to check out that object later, you will get the data from the previous object.But the probability of this happening is very slim.The SHA-1 digest length is 20 bytes, which is 160 bits.It takes 2^80 random hash objects to have a 50% probability of a collision (the formula for calculating the probability of collision is p = (n(n-1)/2) * (1/2^160)) ).2^80 is 1.2 x 10^24, or a trillion billion, which is 1,200 times the total number of grains of sand on Earth.Let’s give an example of how to generate a SHA-1 conflict.If 6.5 billion humans on the planet were programming, and each of them was producing code equivalent to the entire history of the Linux kernel (6.5 million Git objects) every second, and submitting it to a huge Git repository, it would take two years to produce enough objects to have a 50% probability of a SHA-1 object conflict, which is smaller than the chance that members of your programming team would be attacked and killed by wolves in unrelated accidents on the same night. |
|---|---|
branch reference
A straightforward way to refer to a specific commit is if it is the commit at the top of a branch, then you can use the branch's name directly in any Git command that needs to reference that commit.
View last commit
For example, if you want to view the last committed object of a branch, assuming that the topic1 branch points to the commit ca82a6d..., then the following commands are equivalent:
$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1 # topic1是分支名If you want to know which branch points to a specific SHA-1, or want to see the abbreviated SHA-1 in any example, you can use a Git probing tool called rev-parse.You can view more information about detection tools in Git Internals.Simply put, rev-parse is designed for low-level operations rather than daily operations.However, sometimes it can be useful when you want to see exactly what state Git is in right now.You can execute rev-parse on your branch
$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949Quote log
HEAD's pointing history
When you are working, Git will save a reference log (reflog) in the background. The reference log records the history of your HEAD and branch references in recent months.
You can use git reflog to view the reflog
$ git reflog
734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy.
1c002dd HEAD@{2}: commit: added some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEADWhenever the location pointed by your HEAD changes, Git will store this information in the reference log history.You can also obtain previous commit history through reflog data.If you want to see the commit pointed to by HEAD five years ago in the repository, you can use @{n} to reference the commit record output in the reflog.
$ git show HEAD@{5}You can also use this syntax to see where a branch was a certain time ago.For example, to see which commit your master branch pointed to yesterday, you can enter
$ git show master@{yesterday}It will show which commit the top of yesterday's master branch points to.This method only works for data that is still in your ref log, so it cannot be used to check commits that are several months old.
You can run git log -g to view reflog information similar to the git log output format:
$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: fixed refs handling, added gc auto, updated
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'It is worth noting that The citation log only exists in the local repository. It is just a log that records what you have done in your own repository. .The reference log in the warehouse copied by others will not be the same as yours. When you clone a new warehouse, the reference log will be empty because you have not operated in the warehouse yet. git show HEAD@{2.months.ago} This command will only show matching commits if you have cloned a project for at least two months - if you have just cloned the repository, it will return no results.
| Tip | Think of the citation log as a Git version of shell history. If you come from a UNIX or Linux background, think of the citation log as a Git version of shell history. The point is that it is only relevant to you and your session, and not to others. |
|---|---|
ancestor reference
Ancestor references are another way of specifying a commit.If you add a ^ (caret) at the end of a reference, Git will interpret it as the previous commit of that reference.Let's say your commit history is:
$ git log --pretty=format:'%h %s' --graph
* 734713b fixed refs handling, added gc auto, updated tests
* d921970 Merge commit 'phedders/rdocs'
|\
| * 35cfb2b Some rdoc changes
* | 1c002dd added some blame and merge stuff
|/
* 1c36188 ignore *.gem
* 9b29157 add open3_detach to gemspec file listYou can use HEAD^ to view the previous commit, which is the "parent commit of HEAD":
$ git show HEAD^
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'| Note | Escape carets on Windows cmd.exe in, ^ is a special character and therefore needs to be treated differently.You can double-write it or put the commit reference in quotes: $ git show HEAD^ # 在 Windows 上无法工作 $ git show HEAD^^ # 可以 $ git show "HEAD^" # 可以 |
|---|---|
You can also add a number after ^ to indicate which parent commit you want - for example d921970^2 stands for "d921970's second parent commit" This syntax only works for merged commits, because merged commits have multiple parents.The first parent commit of a merge commit is the branch you are merging from (usually master), and the second parent commit is the branch you are merging from (e.g. topic):
$ git show d921970^
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
added some blame and merge stuff
$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
Date: Wed Dec 10 22:22:03 2008 +0000
Some rdoc changesAnother way to indicate an ancestor commit is ~ (tilde).It also points to the first parent commit, so HEAD~ and HEAD^ are equivalent.The difference is when you add the numbers at the end.HEAD~2 stands for "the first parent submission of the first parent submission", which is also the "grandfather submission" - Git will get the corresponding first parent submission according to the number of times you specify.For example, in the previously listed commit history, HEAD~3 would be
$ git show HEAD~3
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
ignore *.gemIt can also be written as HEAD~~~, which is also the first parent commit of the first parent commit:
$ git show HEAD~~~
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
ignore *.gemYou can also combine the two syntaxes - you can use HEAD~3^2 to get the previously referenced second parent commit (assuming it's a merge commit).
Commit interval
You've learned how to commit a single time, now let's take a look at how to specify a range of commits.This is very useful for managing your branches when you have many branches. You can use commit intervals to solve the problem of "What commits on this branch have not yet been merged into the main branch?"
double dot
The most common syntax for specifying commit intervals is double dot.This syntax allows Git to select commits that are in one branch but not another.For example, you have the following commit history Example history for range selection.

Figure 137. Example history for range selection.
You want to see what commits in the experiment branch have not yet been merged into the master branch.You can use master..experiment to tell Git to display these commits.That is, "commits that are in the experiment branch but not in the master branch".To keep the example simple and clear, I used the letters of the submitted objects in the diagram instead of the output of the real log, so it will show:
$ git log master..experiment
D
CConversely, if you want to see commits that are in the master branch but not in the experiment branch, you just swap the branch names.experiment..master will show commits that are in the master branch but not in the experiment branch:
$ git log experiment..master
F
EView content about to be pushed to the remote end
This allows you to keep the experiment branch up to date and see what you are about to merge.Another common scenario is to view the content you are about to push to the remote end:
$ git log origin/master..HEADThis command will output commits that are in your current branch but not in the remote origin.If you perform git push and your current branch is tracking origin/master, the commits output by git log origin/master..HEAD are the commits that will be transferred to the remote server.If you leave one side blank, Git will default to HEAD.For example, git log origin/master.. will output the same result as the previous example - Git uses HEAD instead of leaving it blank.
More
The double-dot syntax works well, but sometimes you may need more than two branches to determine the revision you need, such as to see which commits are included in one of certain branches, but not on your current branch.Git allows you to precede any reference with the ^ character or --not to indicate a branch that you don't want the commit to be included in.Therefore the following three commands are equivalent:
$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refAThis syntax is useful because you can specify more than two references in the query, which is not possible with the double-dot syntax.For example, if you want to view all commits that are included in refA or refB but are not included in refC, you can use either of the following commands:
$ git log refA refB ^refC
$ git log refA refB --not refCThis forms a very powerful revision query system, which allows you to see what is included in your branch.
three o'clock
The last major interval selection syntax is three-point. This syntax can select two references. one of Commits that are included but not included by both.Take another look at the commit history from the previous two-dot example.if you want to see master or experiment For commits that are included in but not common to both, you can do:
$ git log master...experiment
F
E
D
CThis is the same as the usual log output sorted by date, which only gives information about 4 commits.
In this case, a common argument to the log command is --left-right, which will show which side of the branch each commit is on.This will make the output data clearer.
$ git log --left-right master...experiment
< F
< E
> D
> CWith these tools, you can easily view the commits in your Git repository.