3

Please help me to write a batch file for git rebase which unites two last commits: HEAD and HEAD~1 in current branch into one without using interactive editor.

Assume that both commits have single parent and are not pushed yet.

a683ec1 Not pushed 2
c7b480a Not pushed 1
f0e81fb Pushed

I want to leave "Pushed" commit and one commit behind it that will contain "Not pushed 1" + "Not pushed 2" in a final state of "Not pushed 2".

Paul
  • 25,812
  • 38
  • 124
  • 247
  • Do you really need a _batch_ (`.bat` or `.cmd`, for interpreting with `cmd.exe`) or would any kind of script do? Git always requires POSIX shell, even on Windows, and that is a much more pleasant environment to script. – Jan Hudec May 30 '14 at 07:47
  • Do you intend to write commit message manually, provide a short commit message as argument, use message of first commit, use message of second commit or concatenate the commit messages (handling the commit message seems to be the most involved part of the procedure, actually). – Jan Hudec May 30 '14 at 07:52
  • Possible duplicate of [Is there a way to squash a number of commits non-interactively?](http://stackoverflow.com/questions/7275508/is-there-a-way-to-squash-a-number-of-commits-non-interactively) – Ciro Santilli OurBigBook.com Jul 18 '16 at 12:47

1 Answers1

4

The idea would be to do a:

git reset --soft @~ # reset HEAD, preserve current working tree and index
git commit --amend -m "squash HEAD and HEAD~"

That doesn't address the commit messages though: the one from ORIG_HEAD would be lost.
torek addresses that in the comments.

If you have multiple commits to squash (since origin/master), what you can do is (supposing you don't have any work in progress):

echo "squash everything since origin/master" > /tmp/msg
git log  --format=%B origin/master~3.. >> /tmp/msg
git reset --soft origin/master
git commit -F /tmp/msg

This time, you don't amend the commit you reset to (since origin/master was already pushed), but you create a new one.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Doesn't `git reset --hard` lose commits? Is amend better than rebase? – Paul May 30 '14 at 07:56
  • @Paul I have edited the answer: I want to preserve the current working tree, but reset the index and `HEAD` to `HEAD~`. Then I add everything, and amend the current commit, leaving a `HEAD~` (now new `HEAD`) with all the modifications that were in `ORIG_HEAD`. – VonC May 30 '14 at 08:00
  • Thank you for the script, it works, but with one problem: It works only the first time. If I execute this batch repeatedly I am expecting to see one commit fewer in `git log --oneline` but am seeing the same amended commit and commit before it. (Yes, there are more than two commits before pushed one). – Paul May 30 '14 at 08:13
  • @Paul strange, considering `HEAD` is always reset to `HEAD~` – VonC May 30 '14 at 08:15
  • @Paul "Yes, there are more than two commits before pushed one": you can reset `HEAD` to `HEAD~n`, with `n` being the number of commit to squash. Thay way, no need to repeat the script. – VonC May 30 '14 at 08:16
  • It would actually be easier to *keep* the index. Because the `git add -A` might add things that were _not_ versioned in `ORIG_HEAD`. – Jan Hudec May 30 '14 at 08:25
  • @VonC: yes, I can do so, can list `git log` and count comments manually but would like to have an easy-to use batch file with as few input parameters as possible. Ideally - with one parameter - comment. Then I could execute it again and again until I come down to desired commit. – Paul May 30 '14 at 08:38
  • @Paul why counting the commits manually? What has been pushed is referenced by `origin/master`. I have edited my answer to avoid that. – VonC May 30 '14 at 09:37
  • @JanHudec indeed. In that case, I don't think any `git add` is needed. – VonC May 30 '14 at 09:40
  • @VonC: Indeed, `git add` is not needed. And not desired. – Jan Hudec May 30 '14 at 09:46
  • Also, you can gather up all the original log messages of the to-be-squashed commits using `git log origin/master..` before doing the `git reset --soft` (add any formatting desired). Save to a temporary file, use as template or message for new commit. – torek May 30 '14 at 09:52