9

I made a branch of trunk and been submitting/committing lots of changes. Every so often I would update the branch by merging from trunk (eg. 20 commits, then a merge-update, 20 more commits then a merge-update, etc).

Now I would like to squash everything in my branch. How can I do this (using either Git Extensions or console)?

I tried typing:

git rebase -i HEAD~200

but I don't know how many commits to squash. I tried counting the commits in Git Extensions but it's hard to see since it shows a mixture of everything from branch commits and trunk commits. The menu "Show current branch only" doesn't help.

3 Answers 3

12

To rebase all commits made since branching out from master you might use the following command:

git rebase -i `git merge-base HEAD master`

git merge-base finds the closest common ancestor between your current branch and the master (i.e. the last commit that is available on both).

After passing it to the git rebase you get list of all commits since branching out from master (or whatever branch you will put in there) which you can freely squash.

Note: this will not differentiate between yours and merge commits, but as far as I understand that's not what you're looking for.

Note 2: beware that rewriting history after pushing to remote repo might require force-pushing, which is very troublesome when working on a single branch with other people.

7
  • I am the only one working on the branch... so your method/way should be fine right?
    – And Wan
    Commented May 15, 2017 at 13:41
  • excellent, it seems to have rearranged the commits and I can see all the commits nicely sorted and together... I then used tortoisegit, selected all my commits and "combine"...
    – And Wan
    Commented May 15, 2017 at 13:55
  • though, do you think tortoisegit - combine commits is the same as squash command? what would've been the equivalent squash commandline?
    – And Wan
    Commented May 15, 2017 at 14:02
  • Actually, when you rebase a branch using method above, you can just replace the pick keyword with squash in each line, which will cause the squash to be performed on all commits. Commented May 15, 2017 at 14:03
  • This link might be helpful - the guy does exactly that, but with 3 latest commits. devroom.io/2011/07/05/git-squash-your-latests-commits-into-one Commented May 15, 2017 at 14:06
8

Since you need to squash so many commits, you can use the way below:

Assume myBranch original like:

...M---A---B---...---N---...---X  myBranch

If you need to squash commits from A to X, you just need to find the parent of commit A (as commit M in above graph), and then use the commands

git checkout myBranch
git reset --soft <commit id for M>
git commit -m 'squash commit from A to X'

Then the commits on myBranch will be (the squash commit is S):

...M---S  myBranch
6
  • how can I find the commit ID number?
    – And Wan
    Commented May 15, 2017 at 13:44
  • There are many ways, such as git log --oneline --decorate --graph --all and gitk --all.
    – Marina Liu
    Commented May 15, 2017 at 14:14
  • is the commit # the long SHA1 ID? or the short one which I see from git log?
    – And Wan
    Commented May 15, 2017 at 14:18
  • The hash ID is the long one, but any hash ID can be shortened down to as little as four characters as long as the result is unambiguous. For instance if the hash ID is feeddad1deadc0ffeebedbeadbadcafebeef4cab... you can use just feed as long as nothing else in your repository also starts with feed. If something does, you might need feedd or feedda or feeddad or even feeddad1dea. When Git shortens these IDs, it generally (though not always) gives you one that's suitable for putting back into Git.
    – torek
    Commented May 15, 2017 at 19:20
  • @AndWan both long and short string are stand for the same commit id. A commit id (sha-1) is calculate with 40 hex characters, you can also use more than 4 characters at start to repensent (as torek said).
    – Marina Liu
    Commented May 16, 2017 at 3:15
0

This code will rebase in interactive mode your current branch commits and it will put rebased commits on top of master

git rebase -i HEAD~$(git rev-list --count origin/master..) && git pull --rebase origin master

Not the answer you're looking for? Browse other questions tagged or ask your own question.