I am at the commit on master
, and I need to get to the next commit wrt origin/master
.
git log --ancestry-path --date-order --reverse HEAD..origin/master
or a similar git rev-list
command gives me the right commits, properly reversed, so I could |head -n 1
that and be done with it.
However, I wonder it it's possible to get it by using just one process (one git invokation). Limiting with -1
limits first, and then reverses the list, which I not what I need.
How to accomplish this?
I know what a DAG is, I also know enough graph theory to understand why -1
behaves like that. What I'm asking here is not a matter of theory, it's a matter of using a tool used in software development.
I'm 90% confident this can't be done in a single Git invocation for two reasons.
It just doesn't look like they've implemented it. Commits have pointers to their parents, not their children, which is why --max-count
(-1
) and --skip
(which I also tried a bit) run before --reverse
. Since Git's capable of printing in --reverse
or not, it seems like running -1
afterwards should be technically feasible, but perhaps there's an underlying reason it's not. Or perhaps they considered it and decided anyone could just --reverse | head -n 1
like you're doing.
More importantly, you're not guaranteed a unique next commit, even when using --ancestry-path
, so picking --reverse -1
is ambiguous. Here's an example from the --ancestry-path
description in the git-log docs, where your HEAD
could be commit E
. If you're happy with --date-order
, it's more of an academic issue, but the DAG nature of Git makes the whole "next commit" concept unsound.
As an example use case, consider the following commit history:
D---E-------F / \ \ B---C---G---H---I---J / \ A-------K---------------L--M
A regular D..M computes the set of commits that are ancestors of M, but excludes the ones that are ancestors of D. This is useful to see what happened to the history leading to M since D, in the sense that “what does M have that did not exist in D”. The result in this example would be all the commits, except A and B (and D itself, of course).
When we want to find out what commits in M are contaminated with the bug introduced by D and need fixing, however, we might want to view only the subset of D..M that are actually descendants of D, i.e. excluding C and K. This is exactly what the --ancestry-path option does. Applied to the D..M range, it results in:
E-------F \ \ G---H---I---J \ L--M
This does what you want:
git rev-list --children HEAD...origin/master^ | tail -2 | head -1 | cut -d" " -f 2-
This will even print N children, if the history forks at this point.
You could wrap this into a git alias to make a single command.
For other solutions, see also How do I find the next commit in git?
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