1

I have created a branch for development and it has some useless commits. Now I want to merge the commits to the mainline branch. The only commits I want in the origin/master branch is the latest commit and another commit that squashes the first commit to the second latest commit.

Edit: Sorry if this was not clear, so let me try make it more clear. Let us say I have 5 commits in the dev branch. I want to merge all the changes done in the dev branch to the origin/master branch. The problem is that I want to squash commits #1-4 into one commit and merge that commit and commit #5 to the origin/master branch.

lezzago
  • 271
  • 1
  • 6
  • 15

2 Answers2

4

Depending on the number of commits on that branch, especially those “useless” ones you want to get rid of, you can either do an interactive rebase to get rid of those you do not want, or you can simply cherry-pick the two you actually want to keep:

# check out master and update it first
git checkout master
git merge origin/master

# cherry-pick the latest commit from the development branch
git cherry-pick dev-branch

# cherry-pick the other commit (use the hash from the log)
git cherry-pick theothercommitshash

Afterwards, you have those two commits cleanly on top of master and you can squash them using a soft reset or an interactive rebase.

The problem is that I want to squash commits #1-4 into one commit and merge that commit and commit #5 to the origin/master branch.

That’s actually the perfect use case for interactive rebasing.

Start on the dev branch and run git rebase -i dev~5 to launch the editor with an interactive rebasing plan for the last 5 commits. It should look like this:

pick <hash1> Commit 1
pick <hash2> Commit 2
pick <hash3> Commit 3
pick <hash4> Commit 4
pick <hash5> Commit 5

Change the inner three pick to squash so it looks like this:

pick <hash1> Commit 1
squash <hash2> Commit 2
squash <hash3> Commit 3
squash <hash4> Commit 4
pick <hash5> Commit 5

squash basically means “take the commit but meld it into the previous”. So in this case, commit 1 is being picked as it is, and then commits 2, 3, and 4 are all squashed into it one after another. So you end up with a single commit that contains the changes from all 4 commits.

Save the plan and exit the editor to start the interactive rebasing, and adjust the commit message for the squashed commit when Git prompts you to do that. Eventually, you will end up with just two commits on the branch: The squashed commit, and commit 5 rebased on top of that.

Finally, you can just merge the branch into master and you’re done.

poke
  • 369,085
  • 72
  • 557
  • 602
  • Would I be able to squash the first 4 commits (mentioned in the example I added) after I check out master and update it? If so, could you tell me how I would do that? Sorry, I am fairly new to git. – lezzago Aug 09 '17 at 23:21
  • @lezzago Updated the answer in regards to your update. – poke Aug 09 '17 at 23:41
0

If you don't want to merge all changes in a temporary branch into master, you may employ git cherry-pick:

git checkout master
# Create a new commit in branch master which is equal to the latest
# commit in my_dev_branch
git cherry-pick my_dev_branch

If you want to cherry-pick two commits from my_dev_branch and squash them into single commit in master, then --no-commit is what you need:

git checkout master
git cherry-pick --no-commit <some-commit>
git cherry-pick --no-commit <another-commit>
# Now that all changes are in index, create a new commit
git commit
Oleg Andriyanov
  • 5,069
  • 1
  • 22
  • 36