Squash commits directly on feature without rebase or merge
Asked Answered
C

4

28

I've been reading a little about --squashing commits, but they all seem to be go hand in hand with a --rebase.

I have a feature branch with a set of commits like this:

(Feature)          A --> B --> C --> D --> E --> F --> G
                  /
(Master)  M1 --> M2 --> M3

Suppose I want to merge back to the Master branch, but I want to clean up the commits on my feature first.

Is it possible to:

  • Pick commit B, E and F and squash them together as one commit?

OR

  • Can I only squash the commits that come in order, so squash: (A, B and C), or squash (D, E and F) etc?

Either way, can I do a squash directly on my feature, WITHOUT immidiately initializing a Merge or Rebase with it?

If so, how can I do this with Git?

Casto answered 14/7, 2015 at 14:37 Comment(0)
E
23

In my team's workflow we often merge with upstream in the middle of a bunch of commits, and rebasing could get ugly. I've found this helpful to squash all commits that are ahead of master down into one:

# Commit any working changes on branch "mybranchname", then...
git checkout master
git checkout -b mybranchname_temp
git merge --squash mybranchname
git commit -am "Message describing all squashed commits"
git branch -m mybranchname mybranchname_unsquashed
git branch -m mybranchname

# Optional cleanup:
git branch -D mybranchname_unsquashed

# If squashing already-pushed commits...
git push -f
Ethiopia answered 7/9, 2017 at 16:40 Comment(2)
Maybe you should cite this gist.github.com/n00neimp0rtant/9515611Rattray
Before doing the above merge master into your feature branchCrusted
E
8

This works if the commits are local and have not been pushed yet:

git reset --soft HEAD~x
git commit -m "whatever"

Where x is the number of commits you want to squash

Not sure how this would work if the commits you want to squash are on the remote also - if that was the case you "might" need to:

git push -f 

after running the above commands. The usual warnings of git push -f apply - if there is a need to force push make sure you do sanity checks with git log first (as a force push overwrites the code on the remote)!

Ecdysiast answered 20/1, 2021 at 12:24 Comment(0)
E
7

Solution: It is possible to squash multiple commits into single one without rebasing. The best option is to create a new temporary branch from master, then merge the messy branch squashed in only single commit into the temporary branch, then making a pointer to it in your working branch and after delete the temporary one.

Lets assume:

  • master is your master branch,
  • feature is your messy working branch
  • temp is your temporary branch

How to do it?

git checkout -b <temp> <master>
git merge --squash <feature>
git commit -m "your single message"
git checkout <feature>
git reset --hard <temp>
git push -f
git branch -D <temp>

Before:

(Feature)          A --> B --> C --> D --> E --> F --> G
                  /
(Master)  M1 --> M2 --> M3

After:

                           AG --> 
                          /
(Master)  M1 --> M2 --> M3 
Earnest answered 2/2, 2020 at 15:16 Comment(0)
E
5

Yes and no.

Yes, you can avoid changing the parent of commit 'A' but I believe you can't avoid git rebase. You can do interactive rebase on the same root:

git rebase -i M2 Feature

Then you can do whatever you want and at the end branch Feature will still start from commit M2.

Encipher answered 14/7, 2015 at 15:10 Comment(2)
This is what I came here for. A way to squash only certain commits within the feature branch, without involving master. Thank you!Unconformity
Btw if there are any doubts about what is a M2 (base feature branch commit) in your particular case, git merge-base <feature> <master> might be helpful.Boggess

© 2022 - 2024 — McMap. All rights reserved.