Git: How to squash all commits on branch

GitVersion Control

Git Problem Overview


I make new branch from master with:

git checkout -b testbranch

I make 20 commits into it.

Now I want to squash those 20 commits. I do that with:

git rebase -i HEAD~20

What about if I don't know how many commits? Is there any way to do something like:

git rebase -i all on this branch

Git Solutions


Solution 1 - Git

Another way to squash all your commits is to reset the index to master:

git checkout yourBranch
git reset $(git merge-base master $(git branch --show-current))
git add -A
git commit -m "one commit on yourBranch"

This isn't perfect as it implies you know from which branch "yourBranch" is coming from.
Note: finding that origin branch isn't easy/possible with Git (the visual way is often the easiest, as seen here).

Note: git branch --show-current has been introduced with Git 2.22 (Q1 20219).


EDIT: you will need to use git push --force


Karlotcha Hoa adds in the comments:

> For the reset, you can do > > git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD)) > > [That] automatically uses the branch you are currently on.
And if you use that, you can also use an alias, as the command doesn't rely on the branch name.


sschoof adds in the comments:

> Since my default branch is called main and my search had multi times brought me here:
To copy it for my next time > > git reset $(git merge-base main $(git rev-parse --abbrev-ref HEAD))

Solution 2 - Git

Checkout the branch for which you would like to squash all the commits into one commit. Let's say it's called feature_branch.

git checkout feature_branch
Step 1:

Do a soft reset of your origin/feature_branch with your local main branch (depending on your needs, you can reset with origin/main as well). This will reset all the extra commits in your feature_branch, but without changing any of your file changes locally.

git reset --soft main
Step 2:

Add all of the changes in your git repo directory, to the new commit that is going to be created. And commit the same with a message.

# Add files for the commit.
git add ...
git commit -m "commit message goes here"

Solution 3 - Git

What you're doing is pretty error-prone. Just do:

git rebase -i master

which will automatically rebase only your branch's commits onto the current latest master.

Solution 4 - Git

Another simple way to do this: go on the origin branch and do a merge --squash. This command doesn't do the "squashed" commit. when you do it, all commit messages of yourBranch will be gathered.

$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
 > [status 5007e77] Squashed commit of the following: ...

Solution 5 - Git

Assuming you were branching from the master, you don't need to enter yourBranch into the reset step all the time:

git checkout yourBranch
git reset --soft HEAD~$(git rev-list --count HEAD ^master)
git add -A
git commit -m "one commit on yourBranch"

Explanation:

  • git rev-list --count HEAD ^master counts the commits since you made your feature branch from the master, f.ex. 20.
  • git reset --soft HEAD~20 will make a soft reset of the last 20 commits. This leaves your changes in the files, but removes the commits.

Usage:

In my .bash_profile I have added an alias for gisquash to do this with one command:

# squash all commits into one
alias gisquash='git reset --soft HEAD~$(git rev-list --count HEAD ^master)'

After reseting and committing you need to do a git push --force.

Hint:

If you're using Gitlab >= 11.0 you don't need to do this anymore as it has a squashing option when merging branches. Gitlab Squashing option

Solution 6 - Git

Solution for people who prefer clicking:

  1. Install sourcetree (it is free)

  2. Check how your commits look like. Most likely you have something similar to this enter image description here

  3. Right click on parent commit. In our case it is master branch.

enter image description here

  1. You can squash commit with previous one by clicking a button. In our case we have to click 2 times. You can also change commit message enter image description here

  2. Results are awesome and we are ready to push! enter image description here

Side note: If you were pushing your partial commits to remote you have to use force push after squash

Solution 7 - Git

Based on reading several Stackoverflow questions and answers on squashing, I think this is a good one liner to squash all commits on a branch:

git reset --soft $(git merge-base master YOUR_BRANCH) && git commit -am "YOUR COMMIT MESSAGE" && git rebase -i master

This is assuming master is the base branch.

Solution 8 - Git

Since I had some trouble with the solutions proposed here, I want to share a really simple solution (which really works regardless):

git merge origin/master && git reset --soft origin/master

The preceding merge cmd ensures, that no recent changes from master will go on your head (inverted) when committing! After that, just commit the changes and do git push -f

Solution 9 - Git

Solution - 1

A. Pull master into your feature branch (Make sure to update your Master)

git pull origin master  

B. Do soft reset to master

git reset --soft master

C. Commit your changes

git commit -m “commit message"

D. Do git push

git push --force  

Solution - 2

Squashing Commit using git rebase

A.

$git rebase -i HEAD~3  (HEAD~<no. of commits you want to squash>)

B. You will get one interactive prompt where you need to Pick the top commit and insert squash or s in front of those which you want to combine/squash.

Note: Make sure do changes in insert mode and save the file ; (wq in VI Editor)

C. Now you will get another interactive prompt where you need to put # in front of commits message that you don't want, and or add your own message. Again save the file and your commits will successfully rebase.

Cheers!

Solution 10 - Git

How

You need to get the merge base of your branch

git merge-base master your-branch
# 566f8438e0cd0e331ceb49a9cb0920143dfb065c

Then you can rebase to it

git rebase -i 566f8438e0cd0e331ceb49a9cb0920143dfb065c
# then squash/pick/do commit messages

or just do a soft-reset and commit everything

git reset --soft 566f8438e0cd0e331ceb49a9cb0920143dfb065c
git add .
git commit -m "The only commit"
Automate

If you do this often you can automate it by putting these in your .bashrc using.

g-rebase-branch() {
  git branch --show-current | xargs git merge-base master | xargs git rebase -i
}

g-one-commit() {
  local last_commit_message=`git show -s --format=%s`
  git branch --show-current | xargs git merge-base master | xargs git reset --soft
  git add -A
  git commit -m "$last_commit_message"
  git commit --amend
}

and then do these directly in the terminal.

g-one-commit

but if you're merging against a different branch than master then you can replace master with "$1" to do this

g-one-commit staging

Solution 11 - Git

If you use JetBrains based IDE like IntelliJ Idea and prefare using GUI over command line:

  1. Go to Version control window (Alt + 9/Command + 9) - "Log" tab.
  2. Choose a point in the tree from which you created your branch
  3. Right click on it -> Reset current branch to here -> Pick Soft (!!!) (it's important for not to lose your changes)
  4. Push the Reset button in the bottom of the dialog window.

That's it. You uncommited all your changes. Now if you'll make a new commit it will be squashed

Solution 12 - Git

You can use tool I've created specifically for this task:

https://github.com/sheerun/git-squash

Basically you need to call git squash master and you're done

Solution 13 - Git

Another solution would be to save all commit logs to a file

git log > branch.log

Now branch.log will have all commit ids since beginning.. scroll down and take the first commit (this will be difficult in terminal) using the first commit

git reset --soft

all commits will be squashed

Solution 14 - Git

Git reset, as mentioned in many answers before, is by far the best and simplest way to achieve what you want. I use it in the following workflow:

(on development branch)

git fetch
git merge origin/master  #so development branch has all current changes from master
git reset origin/master  #will show all changes from development branch to master as unstaged
git gui # do a final review, stage all changes you really want
git commit # all changes in a single commit
git branch -f master #update local master branch
git push origin master #push it

Solution 15 - Git

All this git reset, hard, soft, and everything else mentioned here is probably working (it didn't for me) if you do the steps correctly and some sort of a genie.
If you are the average Joe smo, try this:
https://stackoverflow.com/questions/5308816/how-to-use-git-merge-squash


Saved my life, and will be my go to squash, been using this 4 times since I found out about it. Simple, clean and basically 1 comamnd. In short:


If you are on a branch lets call it "my_new_feature" off develop and your pull request has 35 commits (or however many) and you want it to be 1.

A. Make sure your branch is up to date, Go on develop, get latest and merge and resolve any conflicts with "my_new_feature"
(this step really you should take as soon as you can all the time anyway)

B. Get latest of develop and branch out to a new branch call it "my_new_feature_squashed"

C. magic is here.
You want to take your work from "my_new_feature" to "my_new_feature_squashed"
So just do (while on your new branch we created off develop):
git merge --squash my_new_feature

All your changes will now be on your new branch, feel free to test it, then just do your 1 single commit, push, new PR of that branch - and wait for repeat the next day.
Don't you love coding? :)

Solution 16 - Git

You can do this with subcommands ie

$ git rebase -i HEAD~$(git rev-list --count HEAD ^master)

This will run first count the commits since you diverged from master and then rebase back to that exact length.

Solution 17 - Git

In case you are okay with an answer involving another branch, try git checkout --orphan <new_branch> It allowed me to simply commit ALL files from previous branch as one commit.

This is something like a git merge squash but not quite the same.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3803850View Question on Stackoverflow
Solution 1 - GitVonCView Answer on Stackoverflow
Solution 2 - GitshankyView Answer on Stackoverflow
Solution 3 - GitEeveeView Answer on Stackoverflow
Solution 4 - GitWaZaAView Answer on Stackoverflow
Solution 5 - GitmlesView Answer on Stackoverflow
Solution 6 - GitMarcin SzymczakView Answer on Stackoverflow
Solution 7 - GitTravis ReederView Answer on Stackoverflow
Solution 8 - GitseebiView Answer on Stackoverflow
Solution 9 - GitAlok TripathiView Answer on Stackoverflow
Solution 10 - GitCavemanView Answer on Stackoverflow
Solution 11 - GitEduard StreltsovView Answer on Stackoverflow
Solution 12 - GitsheerunView Answer on Stackoverflow
Solution 13 - GitpranavView Answer on Stackoverflow
Solution 14 - GitMarcusView Answer on Stackoverflow
Solution 15 - GitItaiRodedView Answer on Stackoverflow
Solution 16 - GitRob LopezView Answer on Stackoverflow
Solution 17 - Gituser1889992View Answer on Stackoverflow