Reintegrate: cope with delete-modify conflicts

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.

Junio C Hamano committed Dec 11, 2023 at 12:40 UTC aaf962df4a807886abb21c1a95ba6652a64943eb
1 file changed +21
Reintegrate
+21
@@ -123,6 +123,27 @@ cocci_mark="treewide: apply cocci patch"
123 case "$generate" in
124 no)
125 accept_rerere () {
126 + git ls-files -u -z |
127 + perl -0 -e '
128 + my %path_stage = ();
129 + my @to_remove = ();
130 + while (<>) {
131 + my ($mode, $sha1, $stage, $path) =
132 + /^([0-7]+) ([0-9a-f]+) ([0-3]) (.*)$/;
133 + $path_stage{$path} ||= 0;
134 + $path_stage{$path} |= (1 << ($stage - 1));
135 + }
136 +
137 + while (my ($path, $bits) = each %path_stage) {
138 + if ($bits == 3 || $bits == 5) {
139 + push @to_remove, $path;
140 + }
141 + }
142 + if (@to_remove) {
143 + system(qw(git rm -f), @to_remove);
144 + }
145 + '
146 +
147 if ! git write-tree 2>/dev/null >/dev/null
148 then
149 git rerere remaining