Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does git name-rev do?

Tags:

git

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 ?

like image 823
Number945 Avatar asked Dec 23 '22 03:12

Number945


1 Answers

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.

The purposes are different

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:

  • the commit comes some time after v2.19.1
  • the actual commit's hash ID starts with 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.

like image 176
torek Avatar answered Dec 26 '22 09:12

torek