How to squash commits in one branch?

12,914

Solution 1

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.

Solution 2

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
Share:
12,914
And Wan
Author by

And Wan

Updated on June 04, 2022

Comments

  • And Wan
    And Wan almost 2 years

    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.

  • And Wan
    And Wan almost 7 years
    I am the only one working on the branch... so your method/way should be fine right?
  • And Wan
    And Wan almost 7 years
    how can I find the commit ID number?
  • And Wan
    And Wan almost 7 years
    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
    And Wan almost 7 years
    though, do you think tortoisegit - combine commits is the same as squash command? what would've been the equivalent squash commandline?
  • Wiktor Czajkowski
    Wiktor Czajkowski almost 7 years
    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.
  • Wiktor Czajkowski
    Wiktor Czajkowski almost 7 years
    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-o‌​ne
  • Marina Liu
    Marina Liu almost 7 years
    There are many ways, such as git log --oneline --decorate --graph --all and gitk --all.
  • And Wan
    And Wan almost 7 years
    is the commit # the long SHA1 ID? or the short one which I see from git log?
  • torek
    torek almost 7 years
    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.
  • Marina Liu
    Marina Liu almost 7 years
    @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).
  • And Wan
    And Wan almost 7 years
    This is good, but I think have to be careful, and yes, I must force push back to origin (remote), otherwise if I pull/merge, I get duplicates
  • Wiktor Czajkowski
    Wiktor Czajkowski almost 7 years
    Exactly, but you should always be careful with rewriting git history. Actually, I would advise to avoid it when possible, but that's just an opinion.
  • RainDoctor
    RainDoctor almost 3 years
    This works well for my use case. Thank you.