Merge branch 'ew/rerere'
* ew/rerere: rerere: record (or avoid misrecording) resolved, skipped or aborted rebase/am git-rerere: add 'gc' command. rerere: add clear, diff, and status commands
This commit is contained in:
@ -7,8 +7,7 @@ git-rerere - Reuse recorded resolve
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-rerere'
|
'git-rerere' [clear|diff|status]
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -27,6 +26,38 @@ results and applying the previously recorded hand resolution.
|
|||||||
You need to create `$GIT_DIR/rr-cache` directory to enable this
|
You need to create `$GIT_DIR/rr-cache` directory to enable this
|
||||||
command.
|
command.
|
||||||
|
|
||||||
|
|
||||||
|
COMMANDS
|
||||||
|
--------
|
||||||
|
|
||||||
|
Normally, git-rerere is run without arguments or user-intervention.
|
||||||
|
However, it has several commands that allow it to interact with
|
||||||
|
its working state.
|
||||||
|
|
||||||
|
'clear'::
|
||||||
|
|
||||||
|
This resets the metadata used by rerere if a merge resolution is to be
|
||||||
|
is aborted. Calling gitlink:git-am[1] --skip or gitlink:git-rebase[1]
|
||||||
|
[--skip|--abort] will automatcally invoke this command.
|
||||||
|
|
||||||
|
'diff'::
|
||||||
|
|
||||||
|
This displays diffs for the current state of the resolution. It is
|
||||||
|
useful for tracking what has changed while the user is resolving
|
||||||
|
conflicts. Additional arguments are passed directly to the system
|
||||||
|
diff(1) command installed in PATH.
|
||||||
|
|
||||||
|
'status'::
|
||||||
|
|
||||||
|
Like diff, but this only prints the filenames that will be tracked
|
||||||
|
for resolutions.
|
||||||
|
|
||||||
|
'gc'::
|
||||||
|
|
||||||
|
This command is used to prune records of conflicted merge that
|
||||||
|
occurred long time ago.
|
||||||
|
|
||||||
|
|
||||||
DISCUSSION
|
DISCUSSION
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -246,6 +246,10 @@ last=`cat "$dotest/last"`
|
|||||||
this=`cat "$dotest/next"`
|
this=`cat "$dotest/next"`
|
||||||
if test "$skip" = t
|
if test "$skip" = t
|
||||||
then
|
then
|
||||||
|
if test -d "$GIT_DIR/rr-cache"
|
||||||
|
then
|
||||||
|
git-rerere clear
|
||||||
|
fi
|
||||||
this=`expr "$this" + 1`
|
this=`expr "$this" + 1`
|
||||||
resume=
|
resume=
|
||||||
fi
|
fi
|
||||||
@ -408,6 +412,10 @@ do
|
|||||||
stop_here_user_resolve $this
|
stop_here_user_resolve $this
|
||||||
fi
|
fi
|
||||||
apply_status=0
|
apply_status=0
|
||||||
|
if test -d "$GIT_DIR/rr-cache"
|
||||||
|
then
|
||||||
|
git rerere
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -139,6 +139,10 @@ do
|
|||||||
--skip)
|
--skip)
|
||||||
if test -d "$dotest"
|
if test -d "$dotest"
|
||||||
then
|
then
|
||||||
|
if test -d "$GIT_DIR/rr-cache"
|
||||||
|
then
|
||||||
|
git-rerere clear
|
||||||
|
fi
|
||||||
prev_head="`cat $dotest/prev_head`"
|
prev_head="`cat $dotest/prev_head`"
|
||||||
end="`cat $dotest/end`"
|
end="`cat $dotest/end`"
|
||||||
msgnum="`cat $dotest/msgnum`"
|
msgnum="`cat $dotest/msgnum`"
|
||||||
@ -157,6 +161,10 @@ do
|
|||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
--abort)
|
--abort)
|
||||||
|
if test -d "$GIT_DIR/rr-cache"
|
||||||
|
then
|
||||||
|
git-rerere clear
|
||||||
|
fi
|
||||||
if test -d "$dotest"
|
if test -d "$dotest"
|
||||||
then
|
then
|
||||||
rm -r "$dotest"
|
rm -r "$dotest"
|
||||||
|
@ -169,9 +169,66 @@ sub merge {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub garbage_collect_rerere {
|
||||||
|
# We should allow specifying these from the command line and
|
||||||
|
# that is why the caller gives @ARGV to us, but I am lazy.
|
||||||
|
|
||||||
|
my $cutoff_noresolve = 15; # two weeks
|
||||||
|
my $cutoff_resolve = 60; # two months
|
||||||
|
my @to_remove;
|
||||||
|
while (<$rr_dir/*/preimage>) {
|
||||||
|
my ($dir) = /^(.*)\/preimage$/;
|
||||||
|
my $cutoff = ((-f "$dir/postimage")
|
||||||
|
? $cutoff_resolve
|
||||||
|
: $cutoff_noresolve);
|
||||||
|
my $age = -M "$_";
|
||||||
|
if ($cutoff <= $age) {
|
||||||
|
push @to_remove, $dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (@to_remove) {
|
||||||
|
rmtree(\@to_remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
-d "$rr_dir" || exit(0);
|
-d "$rr_dir" || exit(0);
|
||||||
|
|
||||||
read_rr();
|
read_rr();
|
||||||
|
|
||||||
|
if (@ARGV) {
|
||||||
|
my $arg = shift @ARGV;
|
||||||
|
if ($arg eq 'clear') {
|
||||||
|
for my $path (keys %merge_rr) {
|
||||||
|
my $name = $merge_rr{$path};
|
||||||
|
if (-d "$rr_dir/$name" &&
|
||||||
|
! -f "$rr_dir/$name/postimage") {
|
||||||
|
rmtree(["$rr_dir/$name"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlink $merge_rr;
|
||||||
|
}
|
||||||
|
elsif ($arg eq 'status') {
|
||||||
|
for my $path (keys %merge_rr) {
|
||||||
|
print $path, "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($arg eq 'diff') {
|
||||||
|
for my $path (keys %merge_rr) {
|
||||||
|
my $name = $merge_rr{$path};
|
||||||
|
system('diff', ((@ARGV == 0) ? ('-u') : @ARGV),
|
||||||
|
'-L', "a/$path", '-L', "b/$path",
|
||||||
|
"$rr_dir/$name/preimage", $path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($arg eq 'gc') {
|
||||||
|
garbage_collect_rerere(@ARGV);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "$0 unknown command: $arg\n";
|
||||||
|
}
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
my %conflict = map { $_ => 1 } find_conflict();
|
my %conflict = map { $_ => 1 } find_conflict();
|
||||||
|
|
||||||
# MERGE_RR records paths with conflicts immediately after merge
|
# MERGE_RR records paths with conflicts immediately after merge
|
||||||
|
Reference in New Issue
Block a user