This is an annoying one.
I use this command to merge two branches
git checkout -b temp public/master
git merge -Xtheirs --squash -m "squashed with devtemp" devtemp
I get some conflicts:
CONFLICT (rename/delete): public/github.css deleted in devtemp and renamed in HEAD. Version HEAD of public/github.css left in tree.
Removing public/extra-html/exit-codes.html
Removing public/.gitkeep
Auto-merging package.json
Squash commit -- not updating HEAD
Automatic merge failed; fix conflicts and then commit the result.
How can ignore this type of conflict? I though --theirs/--ours (or whatever the right Git API for those commands is) would solve this type of problem? Is there a better way that actually works?
The -X theirs
strategy-argument only directs merge's conflict resolution for individual conflicts within one file, not for high-level full-file conflicts.
In this case, as the message says, the conflict is that "they" (devtemp
) removed public/github.css
entirely, while "you" (HEAD
) renamed it. Your Git is not sure what to do here and has left the file in place under its new name.
If you wish to do what they did, simply git rm
the file under its new name, so that it is removed. But ... note that renames are detected by content similarity, so it's possible that they did not actually delete that file at all, and instead deleted another file whose content (before being deleted) was pretty similar to a new file you created. In this case, removing the file is probably wrong.
In all cases, whenever doing a merge, it's wise to test the result before committing. This is especially true when using -X
with either ours
or theirs
. Git has no idea what it is combining and merely relies on textual similarity, and can make nonsensical merges, especially when blindly favoring one side in a case of conflict but using both sides' changes where those changes do not conflict (this is what the -X
options do).
Since you were running git merge --squash
, which for some reason suppresses the final git commit
anyway (a la git merge --no-commit
), you will already be expecting to have to run git commit
separately. Just resolve the conflict (and test thoroughly, as always) and commit.
Edit (per comments): if you want to do this programmatically—though I would advise against this—you can use git ls-files --stage
(perhaps with -z
to get better machine-readable output). Any nonzero stage entries imply that the merge failed. The contents of the index will tell you what happened:
git rm -- <path>
) to take "their" deletion.git add -- <path>
) to take their rename. (You will want to set up a test case and verify that this is the right path.)git checkout --theirs -- <path>
to extract their version to the work-tree, then git add -- <path>
to switch to their version.That should, I think, cover all the unresolved cases. Or, if you have a situation where there are never any actual renames, you are getting false hits from Git's rename detection code, and you will want -X no-renames
to disable it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With