]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Reintegrate: cope with delete-modify conflicts
authorJunio C Hamano <gitster@pobox.com>
Mon, 11 Dec 2023 20:40:09 +0000 (12:40 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 Dec 2023 20:40:09 +0000 (12:40 -0800)
A more proper solution is probably to teach "rerere" to remember
what modification (probably indexed via a patch ID for flexibility,
but either the pre- or post-image blob ID without such flexibility
is probably good enough) was deemed "uninteresting" to resolve in
favor of deletion and reapply it when we see another delete-modify
conflict with the same modification, but for now, treat all
delete-modify conflict to be with uninteresting modification.

The way the Reintegrate machinery is used makes it somewhat safer
than it looks---the initial attempt to merge (and come up with a
merge-fix if needed) will always be done using "git merge" and the
resulting commit is manually examined (if only to see if there is a
need for a further merge-fix) before redo-foo script is written out
of the resulting history.  We'll need to deal with a case where a
modifying side need to be kept over the deleting side if/when it
arises, but so far I haven't seen such a case in real life.

Reintegrate

index ddff2664bcda4c149f91ef96d6684431021a5446..db914c698702ca97a3bede14dc89e4323b5ca028 100755 (executable)
@@ -123,6 +123,27 @@ cocci_mark="treewide: apply cocci patch"
 case "$generate" in
 no)
        accept_rerere () {
+               git ls-files -u -z |
+               perl -0 -e '
+                       my %path_stage = ();
+                       my @to_remove = ();
+                       while (<>) {
+                               my ($mode, $sha1, $stage, $path) =
+                                       /^([0-7]+) ([0-9a-f]+) ([0-3])  (.*)$/;
+                               $path_stage{$path} ||= 0;
+                               $path_stage{$path} |= (1 << ($stage - 1));
+                       }
+
+                       while (my ($path, $bits) = each %path_stage) {
+                               if ($bits == 3 || $bits == 5) {
+                                       push @to_remove, $path;
+                               }
+                       }
+                       if (@to_remove) {
+                               system(qw(git rm -f), @to_remove);
+                       }
+               '
+
                if ! git write-tree 2>/dev/null >/dev/null
                then
                        git rerere remaining