Git - how to force merge conflict and manual merge

2019-01-01 08:27发布

问题:

We maintain web application which has common master branch and many parallel branches, one for each installation, each have few specific changes. Source code is managed in git and it is terrific tool when we need transfer features and bugfixes from master branch into parallel ones. But are few files that are sensitive and automatic merging usually give bad results. So merging would be much easier if they can be somehow marked and every merge would result in conflict requiring manual merge.

I searched for an answer :

  1. I am using --no-commit and --no-ff merge options, but it is not the same.
  2. Here and here someone asks the same question but with no solution.
  3. Similar case seems to be how to prevent file being merged using .gitattributes containing: somefile.php merge=ours . I tried to find some merge option which would generate conflict or force manual merge but found none so far.
  4. .gitattributes containing: somefile.php -merge is never merged automatically and therefore forcing manual merge. It is 90% solution, but what I seek is to try automatic merge and mark it as conflict regardless it is successful or not. But this is so far closest to solution. (...thanks Charles Bailey for clarification...)
  5. Someone suggest to write custom merge driver (1, 2), but how to do it is far from clear to me.

edit: variant 4. description

回答1:

Option 5, a custom merge driver, is probably the way to get closest to what you want. It is surprisingly easy to do. Below is an example of one that I think should get you pretty close to the behavior you desire.

First, create a merge driver script called merge-and-verify-driver. Make it executable and put it in a suitable location (you may want to consider checking this script into the repo, even, since the repo\'s config file is going to depend on it). Git is going to execute this shell script to perform the merge of the sensitive files:

#!/bin/bash
git merge-file \"${1}\" \"${2}\" \"${3}\"
exit 1

This just does the default merge behavior that Git itself normally does. The key difference is that the script always returns non-zero (to indicate that there was a conflict, even if the merge was actually resolved without conflicts).

Next, you need to tell Git about the existence of your custom merge driver. You do this in the repo\'s config file (.git/config):

[merge \"verify\"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

In this example, I\'ve put merge-and-verify-driver in the repo\'s top level directory (./). You will need to specify the path to the script accordingly.

Now, you just need to give the sensitive files the proper attributes so that the custom merge driver is used when merging those files. Add this to your .gitattributes file:

*.sensitive merge=verify

Here, I\'ve told Git that any file with a name matching the pattern *.sensitive should use the custom merge driver. Obviously, you need to use pattern that is appropriate for your file(s).



回答2:

Note: this article \"Writing a git merge driver for PO files\" illustrates the kind of manipulation you can do when manually merging a file: you can pre-processed it in order for your manual merge to have certain data ready.

git merge-file can be used, for instance, to DECRYPT (and re-encrypt) files before merging (!)

In your case, exiting your merge driver with a non-0 status ensure that the merge will be a manual one.



回答3:

These two commands seems to have the same effect as using the custom merge driver:

git merge --no-commit your_target_branch
git checkout --conflict merge .   (do not forget the . and run it in the top dir of the repository)

The first command stops the merge before the creation of the merge commit, and the second marks all the files modified in the two branches as a conflict to solve even if there was no conflict originally.