Usually, when you merge two branches, the conflicts appears in the files with something like:
<<<<<<<<<< HEAD
However, I the merge I'm trying to do has conflicts, but I don't know why the file is not changed at all, and therefore does not contain any <<<<<< HEAD
inside.
Here are the command I tried:
$ md5sum myfile.txt
76dd0814b656b23a61d7e8204cd776de myfile.txt
$ git merge --no-ff tmp_branch
warning: Cannot merge binary files: myfile.txt (HEAD vs. tmp_branch)
Auto-merging myfile.txt
CONFLICT (content): Merge conflict in myfile.txt
Automatic merge failed; fix conflicts and then commit the result.
$ md5sum myfile.txt
76dd0814b656b23a61d7e8204cd776de myfile.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: myfile.txt
no changes added to commit (use "git add" and/or "git commit -a")
I don't know if it can have any impact, but I'm using git-crypt
as backend.
-- EDIT 01 -- I'm pretty sure that it's due a bug in git-crypt. I came up with a quite dirty solution, but that seems to work in the meantime:
First, manually copy the files from the common ancestor commit:
git checkout <your commit>
cp yourfile.txt yourfile_base.txt
Then, manually copy the files in the foreign branch:
git checkout <your branch>
cp yourfile.txt yourfile_other_branch.txt
And finally come back to your main branch and use git merge-file
with something like that:
git checkout master
git merge-file yourfile.txt yourfile_base.txt yourfile_other_branch.txt
Then, you can open yourfile.txt
, search for the string <<<<<
and manually correct the conflicts! If you have a quicker workaround, please let me know!
-- EDIT 02 -- I found a quicker way: instead of checkout & copy, you can do it in one command:
git show <your commit>:./yourfile.txt | git-crypt smudge > ./yourfile.txt<
-- EDIT 03 --
After the suggestion of torek, I finally found a way to solve the problem:
First, add in your .gitattributes
an option merge=git-crypt
for all files managed by git-crypt:
crypt/** filter=git-crypt diff=git-crypt merge=git-crypt
then, add at the end of the file .git/config
the following stuff:
[merge "git-crypt"]
name = A custom merge driver used to merge git-crypted files.
driver = ./my-merge-tool.sh %O %A %B
recursive = binary
and finally create a file at the root of the repo my-merge-tool.sh
containing:
ancestor_decrypted="$1__decrypt"
current_decrypted="$2__decrypt"
other_decrypted="$3__decrypt"
echo ""
echo "###########################"
echo "# Git crypt driver called #"
echo "###########################"
echo ""
echo "Decrypting ancestor file..."
cat $1 | git-crypt smudge > "${ancestor_decrypted}"
echo "Decrypting current file..."
cat $2 | git-crypt smudge > "${current_decrypted}"
echo "Decrypting other file..."
cat $3 | git-crypt smudge > "${other_decrypted}"
echo ""
echo "Merging ..."
git merge-file -L "current branch" -L "ancestor branch" -L "other branch" "${current_decrypted}" "${ancestor_decrypted}" "${other_decrypted}"
exit_code=$?
cat "${current_decrypted}" | git-crypt clean > $2
echo "Removing temporary files..."
rm "${other_decrypted}" "${ancestor_decrypted}" "${current_decrypted}"
if [ "$exit_code" -eq "0" ]
then
echo "@@@ No conflict!"
else
echo "@@@ You need to solve some conflicts..."
fi
exit $exit_code
and make sure it's executable:
chmod +x my-merge-tool.sh
That's all, you can now merge, cherry-pick, and even use your favorite mergetool as usual !