3

I frequently use "fixup!", "squash!" and "rebase -i" to clean up, correct, or just fiddle with recent, unpushed history. I'd like to find a way to get Git to automatically choose which commit makes the most sense for interactive rebasing, so that I could define an alias to do a quick interactive rebase.

I think the best commit in such cases would be the most recent ancestor to either:

  • appear in any other branch (local or remote)
  • have more than one parent
  • have no parents

The first condition ensures that I don't rewrite commits that might affect others. The second ensures that I don't try to rebase "through" a merge, which is definitely not what I want. The third is just a sanity check.

So the question is, how do I use Git find that commit?

Parker Coates
  • 8,520
  • 3
  • 31
  • 37

2 Answers2

1

Not exactly what you’re looking for, but calling git rebase without giving a starting point will make the rebase start at the upstream branch, which is a perfect selection in most cases. Rebasing any further would cause you to rewrite published history, which is never a good idea.

Chronial
  • 66,706
  • 14
  • 93
  • 99
  • Good tip, but I should note that this is new in Git 1.7.6. In versions between 1.7.0 and 1.7.5 you can do the same thing with `git rebase -i @{upstream}` or just `git rebase -i @{u}`. – Parker Coates Feb 22 '13 at 13:37
0

So it's not pretty, but this is what I've come up with.

#! /bin/sh

commit=$(git rev-parse HEAD)

while [ "$(git log --format="%p" -1 $commit | wc -w)" -eq 1 ] \
      && [ "$(git branch --all --contains $commit | wc -l)" -eq 1 ]
do
    commit=$(git rev-parse "$commit^")
done

echo $commit

I'm sure there's a simpler, more robust way of accomplishing this, but it seems to do what I want. Suggestions and improvements are very much welcome. (It'd be nice to do this with just Git plumbing instead of relying on wc, for example.)

Parker Coates
  • 8,520
  • 3
  • 31
  • 37