The other day, some crap got committed to master and pushed, accidentally. It didn't belong. Since it was pushed to origin, we don't want to change history*. When it was time to do a git-flow release, a bunch of conflicts stymied the merge from release branch into master. I wanted to say, "Merge this branch into master, but take all the code from the branch; don't worry about what's currently in master."
There's a merge strategy for merging in a branch and ignoring the changes into the branch: the "ours" merge strategy. But there's no "theirs" merge strategy for choosing all the code from the branch. Here is one way to accomplish this:
- Start the merge
general case of merging something into master (or whatever branch you like; master is an example):
git checkout masterThis leaves the merge open, with conflicts. git status shows the files successfully merged (these are in the index) and the files with conflicts (not yet in the index). While the merge is in progress, git is in a special state, something like the below diagram. The objective is to get all the right files into the index and then commit, which will complete the merge.
git merge branchWithGoodCode
- Get all the code from the branch
git checkout MERGE_HEAD -- .Here, MERGE_HEAD means "the tip of the branch we're trying to merge in." MERGE_HEAD is a ref (pointer to a commit) that exists while a merge is in process. This command pulls the files from there into the working directory and index.
The "." at the end is important: when a path is provided as the last argument to git checkout, then git updates the files without changing your current branch. git checkout with no path will switch to that branch. (The -- is optional, but it makes that . harder to miss.)
- Commit to finish the merge
Hurray, now the tree looks like this:
* if the commits that I don't care about existed only locally, not on origin, then I could wipe those commits from the history entirely.
git checkout master
git reset --hard goodBranch
the reset says "take my current branch and move it to point at the same commit as goodBranch." (Keep in mind that a branch is nothing but a label, a pointer to a commit.) The "--hard" says "and while you're at it, replace everything in my working directory with the goodBranch code." The commits that were only on master are gone from the tree, and eventually forgotten.