2

I use git rebase -i HEAD~5 quite a lot to rebase my commits and squash them down into one. Question I have is, is there a shorthand way of doing this but saying to pick/rename the first commit and then squash all the rest? If I have 5 commits for example doing this by hand per commit is fine, but when I have say 40 commits, I don't want to have to go beside 39 of them and put squash or s at the start.

Similarly once I've chosen which commits to pick/rename/squash, when you go to the next screen where it asks you to choose the commit messages to include, is there a shorter way to tell it to comment out all commit messages except for the first one?

JS_Dev
  • 427
  • 4
  • 14

2 Answers2

1

The quickest way to squash commits together is git reset --soft :

git reset --soft HEAD~5
# or
git reset --soft a12345
git commit

If you want to combine it with a rebase -i rewriting : you can use break in your sequencer script :

pick a12345 first commit
pick b23456 2nd commit
pick c34567 3rd commit
...
pick f67890 6th commit

break   # 'break' will temporarily stop the rebase
        # you can type whatever commands you want,
        # (e.g : 'git reset --soft xxx' and 'git commit')
        # followed by 'git rebase --continue'

You may also use exec, but if you are in the middle of a rewriting, beware the fact that commit references (c34567 or HEAD~3) may not be the same once your sequencer script reaches that point :

pick a12345 first commit
pick b23456 2nd commit
pick c34567 3rd commit
...
pick f67890 6th commit

exec git reset --soft HEAD~3  # caution : if some actions already squash or split
                              # commit 4 for example, 'HEAD~3' won't have the
                              # same meaning as what you see now.
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • Thanks for this. Yes sorry I do need to rebase, so I'm not sure a `--soft` would be right for my scenario. – JS_Dev Jun 23 '21 at 07:56
1

If you have the defualt vim editor configured when rebase-ing, you can use visual mode and substitute the lines. When I do git rebase -i I see:

pick c536072 something
pick cf5b2ca something
pick c092c25 something
pick c1b19af something
pick 0261bb1 something
pick 38d9cd4 something

Usually you type i to enter insert mode and type stuff. But instead, type j (one line down) and V 3 j which will select (visually) 4 lines, and then type : (:'<,'> will show up by itself below) and follow by typing s/pick/s and press enter, which will substitute pick for s for all selected lines. After that exit vim with ZZ or :wq<CR>.

vim is a very, very powerful tool and it has extensive documentation available online that you can research - you could create your own function for the work. And you can also work non-interactively on git rebase so create your own shell commands.

And anyway, I have in my git config:

[alias]
    qlAllAddAmendPushForce = "! f() { set -x; git add -A && git commit --amend --no-edit \"$@\" && git push --force-with-lease; }; f"

So that instead of making many almost-empty commits and pushing them, I make first commit, and then amend all the changes to that commit so that almost-empty commits are not there in the first place (I do this when testing gitlab-ci configuration a lot).

KamilCuk
  • 120,984
  • 8
  • 59
  • 111