branching and merging

There is DEVELOP branch. New branch FEATURE has been created. There are a lot of developer commits.

I merge FEATURE branch into DEVELOP branch using:

git checkout develop
git merge --no-ff --no-commit feature
git add .
git commit -m 'message'
git push

git log

I can see all the commits from the FEATURE branch.

What did I do wrong?


You didn't squash your commits together before you merged, so you will still see all commits. And you merged with --no-ff which I think will make it always create a new commit for the merge, and the man page seems to support this.

You seem to have a misunderstanding about what the --no-ff and --ff flags are for. Reading the above man page might help, but my take on it is this.

Assuming that no changes have been made on the main branch you took you current branch from since you took the branch and started making new commits, then when you come to merge the changes back into the main branch you don't need to do a merge at all. You could just pretend that you made the changes on the main branch all along (as nothing has changed there which would require a merge).

This is what the --ff switch gives you and is the default option. It doesn't remove any commits, it just 'replays' them on the main branch.

The --no-ff switch forces git to create a new commit anyway, even though it is not technically needed.

The --ff-only switch forces git to abort the merge if it can't just replay the commits (ie if any additional commits have been made on the main branch since you took the current branch). Again this doesn't remove any of the commits, it just forces history to be linear as no merges can be done.

If you want to make your feature branch commits look like fewer commits you can rebase your changes (although there are other options, I believe that using the --squash option with your commit might work, but I've not used this so check it out and make sure you understand it before you do it on your production code).

What I do, and there are many different possibilities with git, is rebase my feature branch onto the master branch before I do the merge.

git checkout feature
git rebase master -i

this line launches a window which allows you to choose which commits you want to keep and which you want to 'squash' together. I here I choose which commits I want to merge together (to get rid of superfluous 'forgot this file' or 'tried this and it didn't work' commits, grouping the commits into logical structures which define the chunks of work. Often this is a single commit per feature, but not always. You can also choose to rename any group of commits at this point. The man page for rebase shows you the options.

git checkout develop
git merge feature --ff-only

I merge the feature branch into the master with a --ff-only so that history remains linear. If this fails then you checkout feature again and repeat the process.

As I said there are many ways to skin a cat in git, this is what works for me, your mileage may vary.


Git Shows the Entire History of a Branch by Default

The original poster says

I can see all the commits from the FEATURE branch.

What did I do wrong?

This is expected behavior in Git. When you merge a branch B into another branch A, the history of B becomes a part of the history of A, so of course B's commits would also show up in the history of A.

By default, Git shows the entire history of branches, including commits that have been merged into them.

This is true whether you do a fast-forward merge or not . The difference here between a fast-forward merge and a merge done with --no-ff is that --no-ff will force the creation of a merge-commit , even when a simple fast-forward (without a merge commit) would have been possible.

Either way, however, you would still normally see the commit's of all of the branches that have been merged into the current one .

Hiding the History of Merged Commits

If you don't want to see the history of merged commits, you can hide them from the log output by passing in the --first-parent option

$ git log --oneline --graph --first-parent
* e156455 Git 2.0 (HEAD, tag: v2.0.0, https/master)
* 4a28f16 Update draft release notes to 2.0
* 8ced8e4 Git 2.0-rc4 (tag: v2.0.0-rc4)
* 3054c66 RelNotes/2.0.0.txt: Fix several grammar issu
* b2c851a Revert "Merge branch 'jc/graduate-remote-hg-
* 00a5b79 Merge branch 'jc/graduate-remote-hg-bzr' (ea
* df43b41 Merge branch 'rh/prompt-pcmode-avoid-eval-on
* 7dde48e Merge branch 'lt/request-pull'
* 5714722 Merge branch 'jl/use-vsatisfy-correctly-for-
* c29bf4a Merge git://github.com/git-l10n/git-po
* 3fc2aea Merge branch 'kb/fast-hashmap'
* 6308767 Merge branch 'fc/prompt-zsh-read-from-file'

Compare that with the output of viewing the whole history for a branch

$ git log --oneline --graph
* e156455 Git 2.0 (HEAD, tag: v2.0.0, https/master)
* 4a28f16 Update draft release notes to 2.0
* 8ced8e4 Git 2.0-rc4 (tag: v2.0.0-rc4)
* 3054c66 RelNotes/2.0.0.txt: Fix several grammar issues, notably a lack
* b2c851a Revert "Merge branch 'jc/graduate-remote-hg-bzr' (early part)"
*   00a5b79 Merge branch 'jc/graduate-remote-hg-bzr' (early part)
|
| * 896ba14 remote-helpers: point at their upstream repositories
| * 0311086 contrib: remote-helpers: add move warnings (v2.0)
| * 10e1fee Revert "Merge branch 'fc/transport-helper-sync-error-fix'"
* |   df43b41 Merge branch 'rh/prompt-pcmode-avoid-eval-on-refname'
| 
| * | 1e4119c git-prompt.sh: don't assume the shell expands the value of
* | |   7dde48e Merge branch 'lt/request-pull'
|  
| * | | d952cbb request-pull: resurrect for-linus -> tags/for-linus DWIM
* | | |   5714722 Merge branch 'jl/use-vsatisfy-correctly-for-2.0'
|   
| * | | | b3f0c5c git-gui: tolerate major version changes when comparing
* | | | |   c29bf4a Merge git://github.com/git-l10n/git-po
|    
| * | | | | a6e8883 fr: a lot of good fixups
* | | | | |   3fc2aea Merge branch 'kb/fast-hashmap'
|     
| |/ / / / /
|/| | | | |
| * | | | | c2538fd Documentation/technical/api-hashmap: remove source hi
* | | | | |   6308767 Merge branch 'fc/prompt-zsh-read-from-file'

Keeping a Simpler History by Avoiding Merge Commits

When Git users talk about maintaining a "clean history", they're often referring to avoiding the creation of merge commits. This is often the case when frequently updating a feature branch with new changes from the master branch. People want to avoid merge commits in these cases because they don't add much additional informational value when you're looking at the log for the feature branch, and end up being "clutter", "junk", and "noise", making it harder to see the more important changes that have been made.

To avoid that kind of situation, Git users will often rebase the feature branch on top of an upstream branch like master, which will update the feature branch (just like a merge would), but without creating a merge commit. It's in this way that Git users will "keep a clean history", by avoiding the creation of unnecessary merge commits, and thus maintaining a simpler, easier to understand commit history.

See Also

For more information on fast-forward merges vs non-fast-forward merges, see

  • Why does git fast-forward merges by default?

  • Git fast forward VS no fast forward merge

  • 链接地址: http://www.djcxy.com/p/45078.html

    上一篇: 什么是使用的最佳实践

    下一篇: 分支和合并