0

There are two files A and B. One is edited in branch b1. Both were edited in branch b2.

When merging b1 to b2, I am resolving the conflict by deciding that version of file A from branch b1 is correct. However, after the merge, file B doesn't match file A, since B was never edited on branch b1 (file B keeps commits from b2 without any conflicts).

I want to somehow mark file B as edited on b1 in this case, because I know that when file A is changed, then the file B must also follow, even if its content didn't change. (One could say B was edited on b1, but the result of the edit is "no changes").

How to do that? I know about custom merge drivers or setting merge attribute for the file, but those work only if the file has conflict. There is no conflict on file B, there is only an "inconsistency" between A and B. I also found "assume-unchanged" setting, but it seems there is no "assume-changed" option.

  • Are you saying that the conflict that your merge produces is not textual, but semantic? – j6t Mar 03 '23 at 07:42
  • Suppose A has some text, and B has number of lines of this text. I am editing wording in A, but the number of lines stays the same. On the other branch, I am editing both text and number of lines. Now, after the merge, A has new content from branch b1, but B has number of lines from b2 (and it doesn't match). So, when editing A, I want to somehow tell git, that I am also editing B -- but this edit by simple chance happens to produce exactly the same value (i.e. A has the same number of lines, despite being edited). – Piotr Kubiak Mar 03 '23 at 08:29
  • Sorry, this is still very vage. For example, why do you say "edit the number of lines"; why do you not say "insert new text"? It would be helpful if you would edit the question with a tiny example. Show the content of the files before the branches diverged, then the content on each of the branches, then what content Git produced, and finally what content you want to achieve. – j6t Mar 03 '23 at 08:35
  • This was just an example. The files are in proprietary XML format of external software. – Piotr Kubiak Mar 03 '23 at 09:10

1 Answers1

0

There's no way to do this. When you have a normal merge, Git considers exactly three points, the two heads (branches) and a third point, called the merge base, which is usually the most recent common ancestor.

If you perform a merge and both sides have the same blob, then that value is taken. If exactly one side has a change and the other has the same blob as the merge base, then Git adopts that change without invoking any more complicated merge machinery. There's simply no way to make Git cause a conflict here if there isn't one already.

It sounds like what you're doing might be to check in some sort of generated file. If so, don't do that; generate it as part of your build process, which is the simple and easy way to make this work.

If that's not the case, and you're already resolving a conflict, you can make edits to other files that haven't conflicted at the same time as part of the merge commit. You may want to create a CI job that fails if the two files aren't in sync so if someone does a merge by hand that they can't leave things in an inconsistent state.

bk2204
  • 64,793
  • 6
  • 84
  • 100
  • That is exactly what I am trying to avoid -- the need to edit the other file *every* time. I may forget that. I'd love to mark the files as "pairs", and tell git of one of them has conflict, the other one also has one. – Piotr Kubiak Mar 03 '23 at 09:05
  • As for the CI job -- I have one, and it is CI job that found the incosistency and failed. But since I know how to fix it (just copy the other file during merge) I thought I can do that in git. – Piotr Kubiak Mar 03 '23 at 09:09
  • 1
    As I said, that isn't possible automatically. Git doesn't have such a feature and isn't likely to gain one because it means that merging becomes a multi-pass operation, which would be slow. – bk2204 Mar 03 '23 at 09:11
  • Sorry, I need one more clarifictaion. My problem can be extended to my whole codebase. At the begining, both my branches pass CI. After editing the files separately, still both pass. Now I am doing the merge, and CI fails. There is nothing wrong with the merge, it is done properly. Where is the catch in my workflow? My problem would be solved if i copied *all* my code from one branch to the other, but it defeats the purpose of merge in git, all I need is copy. But, there is no copy operation in git, there is merge. – Piotr Kubiak Mar 03 '23 at 09:47
  • If you need completely identical branches, then you can simply use `git checkout -B`, `git reset --hard` (be careful, it destroys any changes in the working tree), `git update-ref`, or possibly `git merge --ff-only`. However, if you have changes on both sides, then you need a merge. – bk2204 Mar 03 '23 at 10:41
  • No, I am not asking how to do the copy. If my branch passes CI, then what is the purpose of merge when it forces me to do another CI? I already did CI on my whole codebase. The problem is that git operates only on files as a "unit of conflict". I believe there are multiple use cases where the conflict is created on pair of files: for example *.cpp and *.h files. If each one is modified on separate branch, there will be no conflict, but CI could easily be broken after merge. It wolud be great if git allowed me to mark both file.cpp and file.h file as a "unit" in terms of resolving conflicts. – Piotr Kubiak Mar 03 '23 at 13:13