6

Every time I want to fixup my latest commit into the second latest commit, I do this

git rebase HEAD~2 -i
<replace pick with fixup on line 2>

Is there a way to do this in an automated script, without human interference?

I tried this and it doesn't work:

git commit --fixup=HEAD
tanguy_k
  • 11,307
  • 6
  • 54
  • 58
iBug
  • 35,554
  • 7
  • 89
  • 134
  • Possible duplicate of [How do I run git rebase --interactive in non-interactive manner?](https://stackoverflow.com/questions/12394166/how-do-i-run-git-rebase-interactive-in-non-interactive-manner) – phd Apr 16 '18 at 10:58
  • @phd Not really, this is a different question that can be solved in many different ways. – iBug Apr 16 '18 at 12:01

4 Answers4

12
git reset HEAD~1 --soft
git commit --amend --no-edit

or

git reset HEAD~2 --soft
git commit -C ORIG_HEAD^ --reset-author 

or

head=`git log -1 --pretty=%H HEAD~1`
git reset HEAD~2 --hard
git merge --squash ORIG_HEAD
git commit -C $head --reset-author

or

head=`git log -1 --pretty=%h HEAD~1`
git reset HEAD~2 --hard
git cherry-pick -n HEAD..ORIG_HEAD
git commit -C $head --reset-author

The first is enough in your case. The other three are just for fun here, which might be useful in other cases.

Update: the explanation of the second:

Suppose we have A-B-C as the latest three commits and C is the head. What you want is to squash B and C into a single commit which reuses B's commit message.

git reset HEAD~2 --soft resets HEAD to A and keeps the changes of B and C in the index and in the working tree. Then a following git commit creates a commit that includes the changes in the index, aka the changes of B and C.

As its name implies, ORIG_HEAD points to the original head, in this case the one before last reset, which is C. And ORIG_HEAD^ means the first parent of ORIG_HEAD, which is B. -C ORIG_HEAD^ means to reuse the commit message of B without edit.

More about --soft, -C and --reset-author.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53
5

Every time I want to fixup my latest commit,

This can be done directly:

git commit --amend

For older commits:

git commit --fixup $commit
git rebase HEAD~n -i --autosquash

This will automatically interpret the fixup! prefixes generated earlier by --fixup (or manually).

user1686
  • 13,155
  • 2
  • 35
  • 54
  • I think I wrote the question wrong. I want to fixup (squash but discard commit message) the latest commit into the previous one. – iBug Apr 16 '18 at 05:03
  • Don't make the commit in the first place, `--amend` the previous one. – user1686 Apr 16 '18 at 06:08
3

I'm still looking for a "canonical" solution with Git itself.

Here's my temporary solution workaround:

EDITOR="sed -i "2s/pick/fixup/'" git rebase -i HEAD~2

Basically just replaced an interactive text editor with sed.

iBug
  • 35,554
  • 7
  • 89
  • 134
0

This seems to work for me, full automatic and does does not require any specific sha or anything:

git commit -a --fixup HEAD ; GIT_SEQUENCE_EDITOR=touch git rebase --interactive --autosquash HEAD~2
JAR.JAR.beans
  • 9,668
  • 4
  • 45
  • 57