ventsyv
ventsyv

Reputation: 3532

Best strategy to squash commits in Git

Let's say I have a feature branch X in which I've committed multiple times and I've pushed the changes. Another developer than commits to X branch multiple times, then pushes the changes. The feature is not complete and I want to merge it in master and squash the commits. What would be the best/easiest way to do that?

If I do

git checkout master
git merge --squash <feature>

That would result in 1 squashed commit to master, but are the commits on the feature branch squashed?

Alternatively, I can do rebase of the feature branch, but then I have to force push because the commits have already been pushed on the remote branch. Isn't that a bad practice?

Thanks

Upvotes: 0

Views: 1046

Answers (2)

torek
torek

Reputation: 488193

git checkout master
git merge --squash <feature>

would result in 1 squashed commit to master,

Correct.

but are the commits on the feature branch squashed?

No, or yes, or perhaps "mu": the question does not make sense. What the feature branch is, at this point, is effectively dead: it should not longer be used. What you have now can be drawn like this:

       ABCD   <-- master (HEAD)
      /
...--*
      \
       A--B--C--D   <-- feature

where ABCD is a single commit that does the same thing as the four commit sequence A--B--C--D. (Note that before the git merge --squash, the name master pointed to commit *.)

You can now point the feature branch to the new commit, using, e.g., git branch -f feature master, giving:

       ABCD   <-- master (HEAD), feature
      /
...--*
      \
       A--B--C--D   [abandoned]

Note that if you instead use:

git checkout <feature>
git rebase -i master

and then change three of the four pick commands to squash, you have wiped out the old feature branch and created a new feature branch and moved the name feature to point to it, in much the same way. What's different is that the name master still points to its original commit, and you're on the new feature:

       ABCD   <-- feature (HEAD)
      /
...--*   <-- master
      \
       A--B--C--D   [abandoned]

You can now git checkout master and git merge --ff-only feature to get the same result as with the earlier git merge --squash method.

In both cases, if anyone else is using the old feature branch, they must accommodate the abrupt change to feature, which has moved such that the original four commits are no longer useful and should stop being used.

Upvotes: 2

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521249

I sense some confusion here, because typically you would want to squash the commits in the feature branch X before you go to merge that branch into master. Doing an actual squash in the master branch itself would involve rewriting the history of that branch, and this is something which should usually be avoided.

The topic of squashing commits in Git has already been handled here, but here are two accessible options. You could do a soft reset, followed by making a new commit:

# assuming you want to squash the 10 latest commits
git checkout X
git reset --soft HEAD~10
git commit -m 'last 10 commits in 1 new commit'

You could also do an interactive rebase:

git checkout X
git rebase -i HEAD~10

This would bring up a window showing the 10 latest commits before the HEAD of the X branch. You could then change pick to squash for all commits except for the oldest commit (the one on the very top). Then, complete the rebase, and all commits will be squashed down to the commit 10 prior to the HEAD.

In both cases, you should be left with an X branch, having squashed commits, and you can then merge into master.

Upvotes: 0

Related Questions