Overwriting and Pushing a Git Branch
In merging my changes against an upstream master, I frequently find myself doing the following:
git checkout somefeature
git checkout -b integration
git rebase master # resolving conflicts along the way
git checkout somefeature
git merge integratio开发者_运维百科n # or rebase, doesn't matter in this example
I'll often find that merging the integration branch back into my feature branch fails do to some conflicts. The first question I have is, "why is this happening if my integration branch is a descendent of somefeature and I've already resolved conflicts against the upstream master?"
If you're wondering why I'm using an integration branch to begin with, it's to prevent polluting my current branch with a half-failed merge.
My current workaround is to do this:
git checkout integration
git branch -f somefeature # overwrite the branch
The problem now is that I can't push my changes back to a remote branch:
git push origin somefeature
! [rejected] somefeature -> somefeature (non-fast forward)
So now I have to remove the remote branch and re-push my changes. This can't be the optimal way to do this, so I'm wondering, "what's the best way to overwrite a branch and push the changes to a remote branch?"
The problem is caused because git rebase
generates a new series of commits that aren't descended from the somefeature
branch, then when you try and merge them back into somefeature
the conflict resolution done during the rebase doesn't apply. If you were to just merge instead of rebase then this would work as the merge commit would descend from the somefeature
branch.
In terms of pushing to the remote branch you can just use --force
to make the push succeed, that will cause problems for anyone else that has a copy of it though.
You could use git merge -s recursive -Xtheirs
, which will auto-resolve conflicts in favor of the integration branch. However, that still does a merge and may not play well with files moving around and such.
However, since your branch is pushed, you have a reason to want to keep its history around. To get the ideal behavior you want, you could use the 'ours' strategy in the integration branch.
git checkout somefeature
git checkout -b integration
git rebase master # resolving conflicts along the way
git merge -s ours somefeature # mark integration as superseding the somefeature branch
git checkout somefeature
git merge integration # this is now a fast-forward, no conflicts
You could make sure your final merge overwrite the destination branch with a merge driver:
See "Can I tell git pull to overwrite instead of merge?" for example.
The idea is to have a custom merge driver with a "keepTheir
" script.
Your first bit of operations is very strange. You make a copy of somefeature. You rebase that against master. Then you go back to that feature and merge it with the rebased equivelant of itself. This is not the way to do things.
Don't over complicate things. If you want the feature branch to start somewhere else instead (like the latest master), just rebase it.
Then push it with --force (or -f). Tell anyone else that was using that feature branch that they have to fetch the changes and adjust anything that they had locally that they didn't push yet.
Merge is better in the case when others have been working on it.
Hope this helps.
精彩评论