Pergunta

I have a git branch, dev, that is exactly where I want my other git branch, master to be. master has some hotfixes on it that are further in the future than the common ancestor of both so this command chain creates complicated and silly merge conflicts:

git checkout master
git merge dev # Complicated merge conflicts. Boo hiss.

What I would like to do is make a new commit on master that has the state of dev HEAD on it. From then on things can proceed in a more sane manner

Example:

dev:    A ---> B ---> C ----> D
master: A ---> Y ---> Z ----> *

A is my common ancestor. Y and Z are conflicting hotfix changes, so the three-way merge between D, A, and Z is a mess.

In the end I want this result:

  • HEAD of master contains the exact same code as the HEAD on dev
  • History is not rewritten, since both branches have been pushed to remotes
  • A nice commit message that explains this mergeish commit
Foi útil?

Solução

You could try using the ours merge strategy:

git checkout dev
git merge -s ours master
git checkout master
git merge dev

The merge to master will create a merge commit, but the result of the commit will ignore all changes made in master. Then you simply fast-forward master to match dev.

From the documentation for merge strategies:

ours

This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side branches. Note that this is different from the -Xours option to the recursive merge strategy.

Outras dicas

To get a new commit on master that gives an exact match to what is on dev you can do the following:

git checkout dev                         # Get the working directory we want.
git symbolic-ref HEAD refs/heads/master  # Move HEAD to master without changing 
                                         # index or working directory.
git commit                               # Create the new commit on master.

This creates a completely new commit separate from the dev branch.

My inspiration comes from here: https://stackoverflow.com/a/6070417/2348315

If you follow this with a merge commit between dev and master would need to resolve these separate histories. Creating a merge commit immediately after this operation should be conflict free but it will have to be a merge commit rather than a fast-forward merge.

This approach would make sense if you were cherry-picking changes across and had got into a conflict situation that you want to resolve in the way you describe. If your workflow though is to merge changes across then @Cupcake 's merge -s ours approach seems a better fit.

  1. fork marster into a new branch hotfix
  2. reset master to the ancestor you want (A)
  3. merge D (== head/dev) into master

for details on reset the great book gitpro : http://git-scm.com/2011/07/11/reset.html

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top