1

How can I, with minimum effort, squash all my commits (even with merges and conflict resolutions) to a single one on a feature branch and then rebase on top of the branch where I started developing from? Don't want to redo conflict resolution that's already done. Keep hassle to a minimum.

Suppose the branches we are talking about are master and featureX.

eftshift0
  • 26,375
  • 3
  • 36
  • 60

3 Answers3

4

The simplest way I know is

git checkout featureX
git merge -m "Bring latest changes from master" master
# magic starts here
git reset --soft master # put featureX branch pointer on top of master tip
# at this point all the changes related to featureX are on staging area
git commit -m "Feature X in a single shot"

There you go. No rebasing, no squashing.

eftshift0
  • 26,375
  • 3
  • 36
  • 60
  • Pretty clever, though this does assume that you want to squash all featureX work down to a single commit. – 0x5453 Feb 21 '19 at 19:44
  • Added a little more info on the question to make it clear – eftshift0 Feb 21 '19 at 19:50
  • Assuming the goal is to merge the changes onto master, add the following: `$ git checkout master; git merge featureX` – chmaynard Aug 22 '20 at 01:16
  • @chmaynard Thanks for the advice. Back then when you wrote I didn't give it much thought but I am giving it now . :-) If that was the intent from the beginning, it would be simpler to just checkout master and merge-squash featureX (instead of using the recipe altogether). – eftshift0 Oct 11 '21 at 13:08
0

First check with git branch, what's your current working branch. Next, if it isn't featureX already, switch to it, using git checkout featureX.

We'll now figure out how many commits there where that you want to squash into one. For this we'll use git log. To get a bit nicer view of it, use git log --graph --decorate --pretty=oneline --abbrev-commit.

Next to do the actual squashing: git rebase -i HEAD~<NUMBER OF COMMITS TO SQUASH> or alternatively use the SHA hash git rebase -i <SHA>. If you need help with this step, here are two pretty nice articles: https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history and https://medium.com/@dirk.avery/the-definitive-git-rebase-guide-dbd7717f9437

Now we want to make sure, we've got the latest version of the master branch. git checkout master followed by git pull origin master (assuming you use origin as upstream) and git checkout featureX.

Finally we can rebase featureX onto master using git rebase master and can push featureX to GitHub, GitLab or where ever we please. git push origin featureX.
Note: if you've previously pushed featureX, you'll need to force push git push origin featureX --force. Make sure to only do this on branches you're working on, that aren't shared, otherwise people will get into troubles.

An article explaining the whole rebase and squash stuff to keep the commit history clean pretty good can be found here: https://blog.carbonfive.com/2017/08/28/always-squash-and-rebase-your-git-commits/

wawa
  • 4,816
  • 3
  • 29
  • 52
-2

It sounds like you want to use squash merges.

git checkout master
git merge --squash featureX
git commit

This applies all the changes to master as though you had merged (or rebased) featureX, as a single "non-merge" commit.

There are a couple reasons for this. It is possible to squash and rebase in one step just by doing an interactive rebase, but (1) there's no real need to do that if you're going to squash away every intermediate commit -in that case squash merging is a workable shortcut; and (2) you noted that there may be intervening branching and merging going on within the featureX history that you're merging in; rebase won't deal with that easily.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • Am I wrong or you would be moving master instead of feature X? The workflow could work with a little more work... more than my recipe? `git checkout --detach master; git merge --squash featureX; git commit -m "single shot for featureX"; git branch -f featureX; git checkout featureX`. – eftshift0 Feb 21 '19 at 19:58