1

I am trying to resolve a git conflict.

Let's say I have a file versions.json which is already existing in the repo:

{
  "a": {
    "name": "component-a",
    "version": 1,
  },
  "b": {
    "name": "component-b",
    "version": 1,
  },
}

Then,

  • there is a CI pipeline with parallel stages. One building "component-a", the second building "component-b", both being in a monorepo.
  • When "component-a" completes, it updates the file and sets "version": 2 in "a"
  • When "component-b" completes, it updates the file and sets "version": 2 in "b"
  • Each component will
  • Do the changes
  • commit the changes
  • do a git pull --rebase
  • do a git push

This fails with a merge conflict:

Rebasing (1/2)
Auto-merging versions.json
CONFLICT (add/add): Merge conflict in versions.json
error: could not apply 29b568d2... <previous commit message>

Components will never change the same line, so there is no real conflict IMO.

I tried to add a pull BEFORE the commit which works most of the time, but as the monorepo is quite big it takes time and some time which results in a race condition where one component commits during the pull of the other.

So I would like to fix it on the final push or pull directly.

Is there a way to do this in an automated fashion without human interaction?

7
  • "Components will never change the same line, so there is no real conflict IMO." Change your O. Conflicts span adjacent lines; that's just a fact. Can you insert a dummy line between "a" and "b"? That way they wouldn't be adjacent. Commented Oct 17, 2023 at 15:02
  • @matt Actually, there are multiple lines in between the changes, I just simplified the file as I thought it does not matter. Commented Oct 17, 2023 at 15:06
  • @matt I updated the OP to reflect the actual file better. Commented Oct 17, 2023 at 15:08
  • 1
    Oh, I see. The problem is not that both sides edit the file. The problem is that both sides create the file. Sorry about that, I wasn't looking closely enough at the evidence. Commented Oct 17, 2023 at 15:28
  • How is this true: When "component-a" completes, it updates the file and sets "version": 2 in "a"', but, the conflict error says "add/add"? Is it creating the file or editing the file? Commented Oct 17, 2023 at 19:15

1 Answer 1

3

The title is a trick question:

How automatically merge non-conflicting changes in the same file?

That's what already happens, and it's what will happen as soon as you fix the actual problem, which is simply that your parallel pipeline stages need to start from a shared commit where the file already exists. The reason is in Git, conflicts can only be automatically resolved in a "Modify vs Modify" scenario. If one or both sides "Add" or "Delete" the file, then automatic conflict resolution will not occur.

Since you are rebasing 2 commits instead of 1, which we can see from the output:

Rebasing (1/2)

And since the conflict is:

CONFLICT (add/add): Merge conflict in versions.json

We know that the first commit being rebased must be the commit where the file gets added, and the second commit is where the file is modified. The first commit is not the same ID for each stage of the pipeline, which is causing the "add/add" conflict.

The fix, is to sync up all of the stages so they are starting from the same commit ID which already includes the file, and from then on re-running the pipeline should be able to auto-resolve the file as you expect, because the line changes are all more than 2 lines apart.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for your reply. Very interesting, what information you can get from the output. But: All stages start from the same commit, the file is definitely existing already before and in all stages and there are only modifications within the file, nothing added.
Then how do you explain that an add/add conflict is indicated, and not a modified/modified conflict?
@jaw Not sure if you saw j6t's comment, but I agree with that question. Can you run the command git log @ @{u} --graph and inspect the output? I suspect you'll see 2 commits on your local branch, the first of which adds the file. Also, if you try git show 29b568d2 you may also see the file being added.
I am 100% sure, that the was was not added. This file exists since years. The commit 29b568d2 is a merge commit where I merged the latest changes from main into the release branch. All stages started with the same commit, I checked that. What exactly am I looking for in the git log graph command?
@jaw It's strange that a merge commit is getting rebased with git pull --rebase. Does this command output 1 or 2: git show -s --format=%p 29b568d2 | wc -w
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.