Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conflict Markers left in files after Resolving Merge Conflict #2427

Open
kraybit opened this issue Feb 9, 2025 · 3 comments
Open

Conflict Markers left in files after Resolving Merge Conflict #2427

kraybit opened this issue Feb 9, 2025 · 3 comments

Comments

@kraybit
Copy link

kraybit commented Feb 9, 2025

There's special case where Conflict Markers (">>>>>" etc) are left inside files when using Fork to resolve a merge conflict:

  • A Common File is create.
  • Branch A deletes the Common File, and creates a new very similar file. (Git thinks the file has been renamed.)
  • Branch B deletes the Common File, and creates a new very similar file. (Git thinks the file has been renamed.)
  • Branch A and B are merged. Git leaves Conflict Markers in files.
  • When using Fork (and SourceTree too for that matter) to resolve the conflict, the Conflict Markers are left in the file.
  • If we Commit the Merge (which is now resolved), there will actually be Conflict Markers committed to the repository.

Here's a script that sets up a repository in the state needed to show the issue:

# BEGIN SHELL SCRIPT --------------------
#   Purpose: Reproduce bug in which GUI
#   merge resolves cause files to contain
#   conflict markers.
#
git init resolve_issue_repos
cd resolve_issue_repos

# To avoid warnings on Windows
printf "* text=auto eol=lf" > .gitattributes
git add -A
git commit -m "Init"

# Alice : Create 'First.txt'
git checkout -b alice
printf "A\nB\nC\nID:0\nD\nE\nF" > First.txt
git add -A
git commit -m "Create First"

# Bob : Create 'B.txt', Remove 'First.txt'
git checkout -b bob
printf "A\nB\nC\nID:2\nD\nE\nF" > B.txt
rm First.txt
git add -A
git commit -m "Create B, Remove First"

# Alice : Create 'A.txt', Remove 'First.txt'
git checkout alice
printf "A\nB\nC\nID:1\nD\nE\nF" > A.txt
rm First.txt
git add -A
git commit -m "Create A, Remove First"

# Merge
git checkout alice
git merge bob
git status

# Done
echo ""
echo ""
echo "= = = = = = = = = = = = = = = = = = = = = = = = = = = = = ="
echo ""
echo ""
echo "Repos is now in a merge-conflict, and ready to show the issue."
echo "Next step is to resolve the conflicts in GUI, and commit."
echo ""
echo "* Do in GUI:"
echo "   * Resolve:"
echo "      First.txt  --- Delete"
echo "      A.txt  --- Choose Alice's branch (Ours)"
echo "      B.txt  --- Choose Bob's branch (Theirs)"
echo "   * Commit Merge"
echo ""
echo "After that, the issue is that the files A.txt and"
echo "B.txt contain conflict markers."
# END SHELL SCRIPT --------------------

How to use

  1. Make a new empty folder, put the provided script in a file "setup.sh"
  2. Open Git Bash, and go to the empty folder
  3. Run the script:

Image

  1. Open Fork for the repository
  2. Chose Alice's branch for A.txt, and Bob's branch for B.txt

Image

  1. Choose any branch for First.txt (Delete it)
  2. Commit
  3. The repos now contains Conflict Markers

Image

Note : We get the same result if we issue the merge from within Fork, instead of letting the script perform the merge. We would then skip the last "Merge" step in the script, and then in Fork: Checkout Alice, then merge in Bob.


  • I'm not sure this is the right bug tracker.
  • This happens in the "real world" with Unity meta files. (They're all very similar)
  • If "not fixable", any ideas for how to workaround this?

Kind regards
/Oscar

@DanPristupov
Copy link
Contributor

DanPristupov commented Feb 9, 2025

First of all, thank you for creating the bash script to reproduce the case 👍.

I confirm the problem.

Looks like there are 2 nested conflicts: the outer conflicts in the path and then the inner conflict in the file content. Currently I couldn't find a way go handle this.

Normally git checkout-index -f --temp --stage=2 -- A.txt resolves to the original version. However, in this case it resolves the unmerged path conflict and leaves the file with the inner conflict. Then there is no way to proceed with the inner conflict. If I run git checkout-index second time, it will simply repeat the same action.

So, looks like such case would require 2 steps to resolve such a conflict, but git doesn't support that.

Those are my brief observations. May be I'm missing something.

P.S. I tried if a different merge-strategy can make any improvement, but it didn't.

@DanPristupov
Copy link
Contributor

May be we should ignore the fact that there are two conflicts and resolve both of them to either A or B state. Technically, it's wrong, but it's probably more or less correct from the user's perspective... Just thinking out loud.

@aondw
Copy link

aondw commented Feb 14, 2025

I came across the same issue today with Unity. Would turning off rename detection in the git config fix the issue?

[diff] renames = false [merge] renames = false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants