gitgit-history

Create relative path expression between two git commits (one ancestor of the other)


If there are two git commits (or refs) A and B, and if A is known to be an ancestor of B in the history, is there an easy way to compute an expression that shows how A can be reached, starting from B (going backwards through the ancestry path)?

In other words, how to generate a description of A, as a relative path that starts out from B - with results like these:

A = B~1 - i.e. A is the direct parent of B (first parent, if B is a merge)

A = B^2 - i.e. A is the 2nd parent of (merge-commit) B

A = B~22^2~3 - i.e. A is the 3rd ("first") ancestor of the 2nd parent of a merge that is the 22nd ("first") ancestor of B

In practice, this might be useful as an indicator of how far two commits are apart in the history graph - sort of a condensed form of what --ancestry-path can show in git log (but also with fewer information).

Can something like this be generated using git built-in tooling...?

I realize that there can well be multiple valid paths, going from B back to A - so any resulting expression won't necessarily be unique.


Solution

  • The partly related question In Git, is there a way to get the "friendly" name for an arbitrary commit? linked by @Joe indeed led me to an easy way to allow for this - so thanks for the input :)

    This can be answered using git name-rev, although name-rev really just works for named refs as reference to build a path for (so that wouldn't work directly with a SHA as reference).

    Creating an intermediate, dummy ref makes it work though, so the following works

    # Set sample values for A + B (B: current HEAD, A: root commit)
    B=HEAD
    A=`git rev-list HEAD | tail -n 1`
    
    git branch tempRefToB ${B}
    git name-rev --name-only --refs=tempRefToB ${A}
    git branch -d tempRefToB
    

    Sample output of the name-rev command gives me what I was looking for (the temporary ref-name can easily be stripped back out from it, as needed):

    tempRefToB~3334