0

I have several repositories with "just the same" package.json and several config files. I have changes made in one repository and want to spread this changes on others. I managed to do just the right thing following these instructions:

  1. git format-patch HEAD^ (from repo with changes)
  2. git remote add patch repo/with/changes (from repo that needs changes)
  3. git fetch patch (from repo that needs changes)
  4. git am -3 path/to/patch/patch --ignore-whitespace --ignore-space-change (from repo that needs changes)
  5. merge conflicts by hands (visual tool)

The problem is with the last step -- I want to automise this one too. Is it possible to define some merge strategy like "merge ours on lines connected with patch, merge theirs on every other conflicted line"? I have rather simple conflicts on package.json file, where conflicting lines are rather from patch (I want these to have), or from package-name and versions of some packages (I want this to leave as it was for the package).

I know, it is better to think of a way how to avoid duplicating and move similar files to some shared package, but yet I have no idea how it can be done for parts like "package.json" and if it's worth it. Any suggestions on this issues are also very appreciated, but the main focus is still on "as-it-is-now" problem with patch. Or maybe some other ways to spread changes on almost coinciding parts of different repos.

The example of thing I want to automerge looks like this (ex. in package.json, other files merged without conflicts and get changes from patch, but I guess in other cases there can be similar problems in other files too)

From first repo (patch origin)

{
    "name": "packageA", 
    ... 
    script A: "..." // <- patch changed something here
    ...             // <- patch changed something here
    script C: "..." // <- patch changed something here
    ...
    dependencies: { 
        somePackage: "versionA"
    }
}

From second repo

{
    "name": "packageB", // <- here is conflict, I want to leave "package B"
    ... 
    script A: "..." // <- here is conflict, I want to get it from patch
    ...             // <- here is conflict, I want to get it from patch
    script C: "..." // <- here is conflict, I want to get it from patch
    ...
    dependencies: { 
        somePackage: "versionB" // <-- here is conflict, I want to leave "versionB"
    }
}
arsonist
  • 175
  • 1
  • 11
  • I'm not sure your proposed strategy makes any sense - by definition, a conflict has changes from _both_ sides of the merge. Perhaps you could give an example of the kind of conflicts you're seeing, and how _you_ know which to keep. Your process also seems muddled: if you're applying the patch manually from a file, you don't need to also add and fetch the other repo as a remote, all the information is in the patch file. Possibly the actual solution is to be smarter when you _create_ the patch, so that there are fewer conflicts in the first place. – IMSoP Jun 21 '21 at 10:40
  • @IMSoP If I don't add and fetch other repo as origin, I run into "fatal: sha1 information is lacking or useless" error. If I don't use "-3" flag, it just fails with "patch does not apply" error -- I guess because it failes to detect changed parts because of conflicts – arsonist Jun 21 '21 at 10:52
  • Hm... what I thought was an aside is beginning to sound central to your problem: you're using a mechanism designed for sharing _history_ between repositories, but you actually just want to share _a single change_. – IMSoP Jun 21 '21 at 10:55
  • @IMSoP The example of thing I want to automerge "name": "packageA", ... script A: "..." +++ ... script C: "..." --- dependencies: { somePackage: "versionA" } "name": "packageB", <- here is conflict, I want to leave "package B" ... script A: "..." +++ <- ... <- here is conflict, this changed are in patch, I want it from patch script C: "..." --- <- dependencies: { somePackage: "versionB" <- here is conflict, I want to leave "versionB" } – arsonist Jun 21 '21 at 10:57
  • @IMSoP I want to share several changes in several files which are not fully coinciding – arsonist Jun 21 '21 at 10:57
  • @IMSoP sure, added example to the question – arsonist Jun 21 '21 at 11:42
  • 1
    If you look at the patch generated by `git commit format-patch`, does it show a change to the `somePackage: "versionA"` line? Because if that line hasn't changed, there shouldn't be any conflict to resolve. I strongly suspect your problem is coming from how you are _generating_ the patch; if the patch only included the lines you actually want to change, you could use a "prefer theirs" merge strategy, but you have some additional changes which _you_ know are unrelated, but just look like more changes to git. – IMSoP Jun 21 '21 at 11:53
  • @IMSoP No, I don't see changes to `somePackage: "versionA"` line in patch, but still there is a conflict in this lines after `git am -3 path/to/patch/patch --ignore-whitespace --ignore-space-change` - maybe because at this point it tries to merge the resulting files, ignoring the patch itself? If I check "accept theirs" at this point, I loose patch changes, and for "accept ours" I'm left with lines `somePackage: "versionA"` changed. – arsonist Jun 21 '21 at 13:27
  • @IMSoP but I see in patch not only '+' and '-' lines, but also 'the context' - maybe here is the problem? But I actually see conflicts in lines, that are in no way presented in patch - neither as '+'/'-' lines nor as a 'context' – arsonist Jun 21 '21 at 13:31
  • @IMSoP - checked another repo - the same patch has successfully automerged for "package.json". I guess the problem is actually in "around patch conflicting part", but with it each strategy breaks "not conflicts, but differences, like `somePackage: "versionA"` – arsonist Jun 21 '21 at 15:04

1 Answers1

1

I tried cherry-pick --strategy-option theirs instead of am -3 and it finally worked - merged without any conflicts keeping all I wanted. I don't know, whether these are merge-strategy features or I somehow failed to make correct patch (it looks normal).

arsonist
  • 175
  • 1
  • 11