0

After running git rebase -i master I always wish to write :2,50s/pick/squash/g in the vim window that opens. Is there a way to automate what will be written to vim?

This answer shows how to write vim commands from shell, but the problem is in my case the git commands open up vim, and it's not in my control.

sachinruk
  • 9,571
  • 12
  • 55
  • 86
  • The editor you use *should* be in your control. Here's [how to change it](https://stackoverflow.com/q/2596805/184546) if you wish. (That is for changing to Vim, but you can change it to your preferred editor.) – TTT Jul 07 '22 at 02:50
  • 2
    Side Note: if you always want to squash down into a single commit, you could consider `git reset --soft` to the parent of the first commit and then make one new commit. (The parent of the first commit will probably always be `git merge-base master HEAD`.) – TTT Jul 07 '22 at 02:55
  • @TTT is it possible to `rebase` instead of `merge`? Apologies if that is a dumb question. – sachinruk Jul 07 '22 at 07:37
  • My suggestion was neither `merge` or `rebase`, and instead use `reset` to effectively squash all of your commits into a single commit. The outcome would be the same as what you're doing with the interactive rebase and squashing all of your commits up into the first one, except with reset you have to write the new commit message yourself. (Compared to with interactive rebase where it will show you the 50 messages at the end and let you edit it, or you can use "f" instead of "s" to avoid that.) The `merge-base` command was simply to help you find the parent of the first commit to reset back to. – TTT Jul 07 '22 at 14:11
  • If you want to test what I'm talking about, the next time you are about to squash all your commits with interactive rebase, make a new branch , and then `git reset --soft $(git merge-base master HEAD)` which will make it look like you just branched off of `master`, and all of your changes will be staged but you won't have any commits yet. Now just `git commit` and write your message. Interactive rebase is a great tool, and I recommend using it, but in some cases the reset may be slightly faster if you just want to squash everything. – TTT Jul 07 '22 at 14:14
  • 1
    Besides @TTT's `git reset --soft` you can also create a new branch name and run `git merge --squash` to build the same commit you'd build with `git reset --soft`. That is, you'll create a new branch based on the merge base commit (perhaps using `master` directly to find it), `git switch` *to* the new branch, then `git merge --squash development-branch`. – torek Jul 07 '22 at 14:28

2 Answers2

4

Create file

~/.vim/after/ftplugin/gitrebase.vim

try
    2;'} s/^pick/squash
    setlocal modified
catch
endtry

Must have filetype plugin on to work.

Matt
  • 13,674
  • 1
  • 18
  • 27
1

You can define a key mapping in ~/.vimrc like this:

nnoremap  ,rb  :2,$ s/^pick/squash/<cr>

Then in the vim session started by git rebase, you just press ,rb if you want to squash all the commits.

Or define as a vim function:

function GitRebaseSquashAll()
    :2,$ s/^pick/squash/
endfunction

and call it with :call GitRebaseSquashAll().

pynexj
  • 19,215
  • 5
  • 38
  • 56