[kwlug-disc] Advanced(?) Git usage question

Chris Frey cdfrey at foursquare.net
Thu Apr 10 02:52:58 EDT 2014


On Wed, Apr 09, 2014 at 03:44:53PM -0400, Adam Glauser wrote:
> My specific questions:
> - is there a Git command that will tell me the revision closest to HEAD
> which has both A and B as ancestors? Kind of the opposite of `git
> merge-base`.

I don't know of any specific git command for this, but some bash might do it.
(If your version of git doesn't have --is-ancestor, see the stackoverflow
URL below)

	A=64d11ba
	B=8ce0697

	for commit in $(git rev-list --merges master ) ; do
		if git merge-base --is-ancestor $A $commit && \
		git merge-base --is-ancestor $B $commit ; then
			echo Found merge point: $commit
			break
		else
			echo $commit does not contain both A and B
		fi
	done

If you want to find the first merge where A and B were made into ancestors,
add --reverse to the rev-list command.



Possibly useful fun facts:


You might be able to play around with --ancestry-path to determine history
a little better.  See the git-rev-list manpage for details.

For example, if you want to see the changes between A and B that are not
on any other intermediate branches:

	git log --ancestry-path A..B

If this shows nothing, try B..A instead, since you said you weren't sure of
the order of A and B.

If this too shows nothing, then they are completely unrelated in git history.

Once you find out which commit is newer, you can use it for comparison
purposes.


Also, remember the triple dot notation.  According to this page:

http://stackoverflow.com/questions/18345157/how-can-i-tell-if-one-commit-is-an-ancestor-of-another-commit-or-vice-versa

Quoting:

	$ git log --oneline --graph --left-right \
		--first-parent --decorate <commit1>...<commit2>

	The above command will show you commits that are reachable
	from commit1 or commit2, but not both, i.e. C1 UNION C2 - C1
	INTERSECTION C2, in terms of set operations.

	If neither commit is a parent of the other, you'll see the
	child commits of both, but if one is an ancestor of the other,
	you'll only see the output for the descendant commit, since the
	ancestor is contained in the path of the descendant, and is thus
	excluded from the output.



> - I'm trying `git bisect`, but this seems more useful if I'm not already
> sure which revisions are the source of the bug. Would you use `git bisect`
> in a situation like this?

Probably not.  That seems like a lot of work.  I'd probably break out
git-rev-list and grep first. :-)


> I think the best practices approach would be to create a branch starting
> with the revision where this feature was introduced (commit B), fix the
> bug, then merge the fix in to whichever other branches need it.

I don't understand why this would be best practices, unless you're trying
to link the fix directly with the original bug.  Maybe I'm just sloppy,
but I'd likely slap the bugfix on the nearest HEAD and merge or cherry-pick
as needed. :-)

The history is still contained at the file level, and putting an english
description of the history of the bug into the bugfix commit, as well
as including the SHA1 of the buggy commit, and maybe a "bugfix:" tag
in the shortlog line, that seems more useful to me than an obscure
internal merge link.  Because this:

	git log buggy-file.c

shows exactly what I need.

The important information, to me, is that it was a specific bugfix, and
there is nothing in git to help me find that except explicit and consistent
commit messages that I can search on.

- Chris





More information about the kwlug-disc mailing list