17

During development I often need to commit and push "intermediate" commits, i.e. commits with the code not compilable or in the middle of changing something, etc. I don't want to make such commits, but this is required for easy continuing my work from office to home, sometimes for other developers to get them base on which they can start their work.

I thought I had found a solution for that problem:

  1. I create a separate "dev" branch and make all intermediate commits.

  2. Once the code is in good state, make a merge to master. So the master wouldn't contain "intermediate" commits but only "normal" commits.

  3. Delete the "dev" branch with all intermediate commits.

But this doesn't work. When I make merge, not only the merge commit is included to master, but also all "intermediate" commits from "dev" branch too. So deleting "dev" branch gives nothing, its "intermediate" commits stay there.

So the questions is: is it possible to make merge in the way that master would include only its own commits + merge commit and not include the commits from the second branch? If it's impossible, could you advice me how to achieve my goal - to have the ability to temporary save intermediate results but also seamlessly delete them later?

Aleksey Shubin
  • 1,960
  • 2
  • 20
  • 39

5 Answers5

24

When you merge your "dev" branch into master, try

git checkout master
git merge --squash dev
git commit -m "Add new feature."

The --squash option will squash all of your intermediate changes into one big change.

You can also use git rebase --interactive if you need more finite control (e.g., reordering commits and doing multiple small squashes). This answer explains the differences between git merge --squash and git rebase --interactive.

Community
  • 1
  • 1
Garrett Hyde
  • 5,409
  • 8
  • 49
  • 55
  • Is squash a good idea given that he's sharing these commits with other developers? – John Szakmeister Feb 12 '13 at 09:49
  • 1
    +1 for mentioning `git rebase -i`. Then people *really* wouldn't know about the local dev branch. – Mike Monkiewicz Feb 12 '13 at 14:34
  • 2
    @jszakmeister, since he is merging changes from a local dev branch to his local checkout of master, it's fine. When he pushes his changes, it will appear to the other developers as if his changes were one giant commit. In other words, squashing allows you to have one commit that says, "Add new feature," in stead of multiple, "Oops. Fix typo," commits. – Garrett Hyde Feb 12 '13 at 14:44
  • He kind of contradicts himself though. In the opening paragraph it says "I don't want to make such commits, but this is required for easy continuing my work from office to home, sometimes for other developers to get them base on which they can start their work...". I took the latter to mean he might share this intermediate state but still want to fix it up later. – John Szakmeister Feb 12 '13 at 16:06
  • @jszakmeister, yes, I share the intermediate state sometimes, but still delete them later, once I know that neither me nor other developers don't need these commits anymore. – Aleksey Shubin Feb 18 '13 at 08:23
4

What you want is a "squash" merge:

git checkout master
git merge --squash dev
git commit -m 'current stable work from dev branch'

What this does is create the same state in your working tree as a regular merge, but does not create a merge commit with all the intermediate commits as ancestors. The intermediate commits will not be part of the history of the master branch. The documentation for this option from the git merge manpage says:

Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit or move the HEAD, nor record $GIT_DIR/MERGE_HEAD to cause the next git commit command to create a merge commit. This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).

Matt McHenry
  • 20,009
  • 8
  • 65
  • 64
0

add another branch called RC (release candidate). This branch will only have merges of completed feature branches. You can keep dev to try out unfinished branches together. You only integrate to master release candidates which contain nothing but merged finished features.

Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141
0

You can use the .patch from GitHub, e.g. https://github.com/rails/rails/pull/123.patch

git apply 123.patch
# review changes, edit files etc.
git add .
git commit -m "committing #123"
Dorian
  • 22,759
  • 8
  • 120
  • 116
-1

You cannot delete commits during a merge. You can squash intermediate commits but this is a bad idea which probably won't work for you as you publish them. You can also squash them into a master branch without making a merge (git merge --squash followed by git commit) then merge the master branch into the dev branch.

wRAR
  • 25,009
  • 4
  • 84
  • 97