According to git name-rev doc ,
Finds symbolic names suitable for human digestion for revisions given in any format parsable by git rev-parse.
But I could not understand this. What is the use of this command ? How is it different from git describe command ? I think that both also does the same thing - give a SHA1 Id , gives us back the nearest reference name to it ?
Marek R's answer is correct, but a bit incomplete.
Essentially, git name-rev
comes up with a name plus some relative expression, if needed, to move from the name to the commit, while git describe
comes up with some name—usually a tag name, but potentially some other name—plus some additional string if needed, that's not particularly "relative": there is a count in some cases, but it's not as useful as the count(s) in git name-rev
. If git describe
was not able to use a raw name, it adds g
and an abbreviated hash ID:
$ git describe
v2.19.1-272-gf84b9b09d4
but:
$ git name-rev HEAD
HEAD master
If we add --all
to git describe
's arguments, git describe
does use the branch name, but the output differs:
$ git describe --all
heads/master
In particular it was careful to note that it was using a branch name, since if there is a collision between branch and tag names—if there is a refs/tags/master
as well—parsing master
alone would produce the hash ID associated with the tag, rather than the branch-name.
Besides these, git describe
can add -dirty
if the work-tree does not match the commit, and—since Git 2.16.0—can produce a name:pathname
string to give you an expression that names a particular stored blob:
$ git describe HEAD:Makefile
v2.19.0-237-ge3d4ff037d:Makefile
which is not something git name-rev
can manage.
What is the use of [
git name-rev
]?
I have never actually seen anyone use it myself, but see below. Let's start with the purpose of git describe
: git describe
is used very commonly to produce useful descriptions of a particular build. Because it defaults to using only tags, its output is relatively stable (well, it is if we assume that tags never change). When git describe
says v2.19.1-272-gf84b9b09d4
, we know:
v2.19.1
f84b9b09d4
and future git describe
outputs for this same commit are likely to be identical (though they could change if we add a new annotated tag). The count of 272 commits reachable via v2.19.1..f84b9b09d4
:
$ git rev-list --count v2.19.1..f84b9b09d4
272
will not change. Running git rev-parse v2.19.1-272-gf84b9b09d4
will always produce f84b9b09d40408cf91bbc500d9f190a7866c3e0f
, whether I do it again tomorrow or next week or next year, as long as tag v2.19.1
remains where it is. If we use this string as a build identifier, and we avoid using branch names and are careful to note if the build is "dirty", we can immediately tell whether we can easily reproduce this same build again later, and if so, how (i.e., by running git checkout v2.19.1-272-gf84b9b09d4
).
On the other hand, when git name-rev
says master
or master~3
or whatever, there's no guarantee that I can go back to that repository tomorrow and use that same expression to find the same commit. Next year, it's almost guaranteed to be wrong. So git name-rev
output is only good for a little while—essentially, until you move some of the branch names.
Meanwhile, git name-rev
has a trick that git describe
does not: it will parse its standard input, looking for things that appear to be hash IDs. When it finds them, it will copy them to standard output and add (expression)
, provided the hash translates to a name:
$ X=$(git rev-parse master)
$ echo embedded $X hash | git name-rev --stdin
embedded f84b9b09d40408cf91bbc500d9f190a7866c3e0f (master) hash
$ Y=$(echo $X | sed s/f/0/)
$ echo embedded invalid $Y hash | git name-rev --stdin
embedded invalid 084b9b09d40408cf91bbc500d9f190a7866c3e0f hash
This means that you can, as shown in the documentation, run git log | git name-rev
and have all of those commit hashes become decorated hashes. However, the hashes do have to be full hashes. Compare:
$ git log --oneline -n 10 | git name-rev --stdin
f84b9b09d4 Sync with 2.19.1
cae598d998 Git 2.19.1
1958ad504b Sync with 2.18.1
268fbcd172 Git 2.18.1
44f87dac99 Sync with 2.17.2
6e9e91e9ca Git 2.17.2
1a7fd1fb29 fsck: detect submodule paths starting with dash
a124133e1e fsck: detect submodule urls starting with dash
e43aab778c Sync with 2.16.5
27d05d1a1a Git 2.16.5
with:
$ git log --pretty=tformat:'%H %s' -n 10 | git name-rev --stdin
f84b9b09d40408cf91bbc500d9f190a7866c3e0f (master) Sync with 2.19.1
cae598d9980661a978e2df4fb338518f7bf09572 (tags/v2.19.1^0) Git 2.19.1
1958ad504befa6a09c475cc8ab9de43b359de137 (tags/v2.19.1~1) Sync with 2.18.1
268fbcd172cdb306e8a3e7143cc16677c963d6cd (tags/v2.18.1^0) Git 2.18.1
44f87dac99574a8073ffb1ba8b10bd4d3945f61b (tags/v2.18.1~1) Sync with 2.17.2
6e9e91e9cae74cd7feb9300563d40361b2b17dd2 (tags/v2.17.2^0) Git 2.17.2
1a7fd1fb2998002da6e9ff2ee46e1bdd25ee8404 (tags/v2.17.2~1) fsck: detect submodule paths starting with dash
a124133e1e6ab5c7a9fef6d0e6bcb084e3455b46 (tags/v2.17.2~2) fsck: detect submodule urls starting with dash
e43aab778c72250e11eb00e31dc6be90072a1637 (tags/v2.17.2~3) Sync with 2.16.5
27d05d1a1a62273aa3749f4d0ab8a126ef11ff66 (tags/v2.16.5^0) Git 2.16.5
Bottom line: use whichever suits your particular purpose best. Which one that is depends on what your purpose is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With