Message ID | xmqqfsxvxjj2.fsf@gitster.g (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | rerere: enable by default | expand |
On 2021-06-06 at 12:30:25, Junio C Hamano wrote: > By default, the rerere machinery has been disabled since a bug in > the machinery could screw up the end user's data at the most > stressful time during the end user's workday (i.e. during conflict > resolution). > > It however has been in wide use without causing much trouble (other > than, obviously, replaying a broken conflict resolution that was > recorded earlier when the user made a mismerge), and it is about > time to enable it by default. Yes, I think this makes sense. I've been using it for quite a while without problems and I'm usually quite good at breaking things, and if we can make the user experience better, which I think rerere does, that's definitely a good thing.
On Sun, Jun 06 2021, Junio C Hamano wrote: > By default, the rerere machinery has been disabled since a bug in > the machinery could screw up the end user's data at the most > stressful time during the end user's workday (i.e. during conflict > resolution). What was that bug & in what commit was it fixed? Makes sense to note that here. > It however has been in wide use without causing much trouble (other > than, obviously, replaying a broken conflict resolution that was > recorded earlier when the user made a mismerge), and it is about > time to enable it by default. > > Signed-off-by: Junio C Hamano <gitster@pobox.com> > --- > Documentation/config/rerere.txt | 5 ++--- > rerere.c | 12 +++--------- > t/t2030-unresolve-info.sh | 3 +++ > 3 files changed, 8 insertions(+), 12 deletions(-) > > diff --git a/Documentation/config/rerere.txt b/Documentation/config/rerere.txt > index 40abdf6a6b..45e97fc0fa 100644 > --- a/Documentation/config/rerere.txt > +++ b/Documentation/config/rerere.txt > @@ -7,6 +7,5 @@ rerere.enabled:: > Activate recording of resolved conflicts, so that identical > conflict hunks can be resolved automatically, should they be > encountered again. By default, linkgit:git-rerere[1] is > - enabled if there is an `rr-cache` directory under the > - `$GIT_DIR`, e.g. if "rerere" was previously used in the > - repository. > + enabled, but this configuration can be set to 'false' to > + turn it off. > diff --git a/rerere.c b/rerere.c > index d83d58df4f..83e740d730 100644 > --- a/rerere.c > +++ b/rerere.c > @@ -18,8 +18,7 @@ > #define THREE_STAGED 2 > void *RERERE_RESOLVED = &RERERE_RESOLVED; > > -/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */ > -static int rerere_enabled = -1; > +static int rerere_enabled = 1; /* default to true */ > > /* automatically update cleanly resolved paths to the index */ > static int rerere_autoupdate; > @@ -852,16 +851,11 @@ static GIT_PATH_FUNC(git_path_rr_cache, "rr-cache") > > static int is_rerere_enabled(void) > { > - int rr_cache_exists; > - > if (!rerere_enabled) > return 0; > > - rr_cache_exists = is_directory(git_path_rr_cache()); > - if (rerere_enabled < 0) > - return rr_cache_exists; > - > - if (!rr_cache_exists && mkdir_in_gitdir(git_path_rr_cache())) > + if (!is_directory(git_path_rr_cache()) && > + mkdir_in_gitdir(git_path_rr_cache())) > die(_("could not create directory '%s'"), git_path_rr_cache()); > return 1; > } > diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh > index be6c84c52a..8c571ddf92 100755 > --- a/t/t2030-unresolve-info.sh > +++ b/t/t2030-unresolve-info.sh > @@ -46,6 +46,7 @@ prime_resolve_undo () { > } > > test_expect_success setup ' > + git config rerere.enabled false && > mkdir fi && > printf "a\0a" >binary && > git add binary && > @@ -127,6 +128,8 @@ test_expect_success 'unmerge with plumbing' ' > ' > > test_expect_success 'rerere and rerere forget' ' > + # from here on, use rerere. > + git config rerere.enabled true && > mkdir .git/rr-cache && > prime_resolve_undo && > echo record the resolution && It seems strange to disable it at the very beginning, but then not have any test until you turn it on actually rely on that except that "mkdir" in the second hunk, i.e. this on top works: diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index 8c571ddf92..7195ded9f9 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -46,7 +46,6 @@ prime_resolve_undo () { } test_expect_success setup ' - git config rerere.enabled false && mkdir fi && printf "a\0a" >binary && git add binary && @@ -130,7 +129,6 @@ test_expect_success 'unmerge with plumbing' ' test_expect_success 'rerere and rerere forget' ' # from here on, use rerere. git config rerere.enabled true && - mkdir .git/rr-cache && prime_resolve_undo && echo record the resolution && git rerere && So the only impact of that rerere.enabled=false early is to make sure we're not creating the .git/rr-cache. Those tests will fail if we turned on rerere.autoUpdate=true there, so isn't it a better test coverage to assert that even with rerere.enabled=true we don't impact these merge resolutions in the earlier tests? It also seems to make sense to change the main rerere tests to assert that we have the default set to this new value, i.e.: diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 9f8c76dffb..f319f08852 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -89,8 +89,8 @@ test_expect_success 'activate rerere, old style (conflicting merge)' ' ' test_expect_success 'rerere.enabled works, too' ' + test_path_is_dir .git/rr-cache && rm -rf .git/rr-cache && - git config rerere.enabled true && git reset --hard && test_must_fail git merge first && @@ -100,8 +100,8 @@ test_expect_success 'rerere.enabled works, too' ' ' test_expect_success 'set up rr-cache' ' + test_path_is_dir .git/rr-cache && rm -rf .git/rr-cache && - git config rerere.enabled true && git reset --hard && test_must_fail git merge first && sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && @@ -668,7 +668,6 @@ test_expect_success 'test simple stage 1 handling' ' ( cd stage_1_handling && - git config rerere.enabled true && git checkout A^0 && test_must_fail git merge B^0 ) As an aside: This pre-dates your change here, but I thought the config reading in rerere.c was a bit odd, why do we call the one-off config reading functions when we're about to iterate over the whole set anyway? Turns out we did it the way I'd expect before 633e5ad326 (rerere.c: replace `git_config()` with `git_config_get_*()` family, 2014-08-07).
"brian m. carlson" <sandals@crustytoothpaste.net> writes: > On 2021-06-06 at 12:30:25, Junio C Hamano wrote: >> By default, the rerere machinery has been disabled since a bug in >> the machinery could screw up the end user's data at the most >> stressful time during the end user's workday (i.e. during conflict >> resolution). >> >> It however has been in wide use without causing much trouble (other >> than, obviously, replaying a broken conflict resolution that was >> recorded earlier when the user made a mismerge), and it is about >> time to enable it by default. > > Yes, I think this makes sense. I've been using it for quite a while > without problems and I'm usually quite good at breaking things, and if > we can make the user experience better, which I think rerere does, > that's definitely a good thing. I agree in principle, but new tests added by topics in flight need to get prepared for the change. There are, for example, misguided checks that insist that the standard error stream out of "git merge" must be absolutely empty, which will break when rerere machinery starts reporting that it prepared the preimage so that it can record the resolution. Not just rerere, but such a test is brittle and will break when other inner parts of the system starts reporting more (e.g. progress) to the standard error stream. I'd prefer to see these tests cleaned up in the right way (as opposed to setting rerere.enabled to false upfront, which hides these suboptimal tests) before this change to enable rerere by default lands, so it may need a sizeable preparatory work. Thanks.
On 06/06/2021 14:30, Junio C Hamano wrote: > By default, the rerere machinery has been disabled since a bug in > the machinery could screw up the end user's data at the most > stressful time during the end user's workday (i.e. during conflict > resolution). > > It however has been in wide use without causing much trouble (other > than, obviously, replaying a broken conflict resolution that was > recorded earlier when the user made a mismerge), and it is about > time to enable it by default. > > Signed-off-by: Junio C Hamano <gitster@pobox.com> > --- > Documentation/config/rerere.txt | 5 ++--- > rerere.c | 12 +++--------- > t/t2030-unresolve-info.sh | 3 +++ > 3 files changed, 8 insertions(+), 12 deletions(-) > > diff --git a/Documentation/config/rerere.txt b/Documentation/config/rerere.txt > index 40abdf6a6b..45e97fc0fa 100644 > --- a/Documentation/config/rerere.txt > +++ b/Documentation/config/rerere.txt > @@ -7,6 +7,5 @@ rerere.enabled:: > Activate recording of resolved conflicts, so that identical > conflict hunks can be resolved automatically, should they be > encountered again. By default, linkgit:git-rerere[1] is > - enabled if there is an `rr-cache` directory under the > - `$GIT_DIR`, e.g. if "rerere" was previously used in the > - repository. > + enabled, but this configuration can be set to 'false' to At the moment, backticks are used more often than single quotes for formatting of boolean values in documentation: $ git grep -oE "\`(false|true)\`" -- Documentation/*.txt Documentation/config/*.txt | wc -l 121 $ git grep -oE "'(false|true)'" -- Documentation/*.txt Documentation/config/*.txt | wc -l 53 > + turn it off.
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes: > On Sun, Jun 06 2021, Junio C Hamano wrote: > >> By default, the rerere machinery has been disabled since a bug in >> the machinery could screw up the end user's data at the most >> stressful time during the end user's workday (i.e. during conflict >> resolution). > > What was that bug & in what commit was it fixed? Makes sense to note > that here. There is no such bug ;-). Writing buggy code, not thinking about it carefully enough and jumping up and down yelling this shiny new toy must be merged down immediately is something we see on this list from others, but it is the total opposite of how I operate. I just am extra cautious and even after I am reasonably sure the code would not break, I prefer to have volunteers to opt into testing. > @@ -130,7 +129,6 @@ test_expect_success 'unmerge with plumbing' ' > test_expect_success 'rerere and rerere forget' ' > # from here on, use rerere. > git config rerere.enabled true && > - mkdir .git/rr-cache && > prime_resolve_undo && > echo record the resolution && > git rerere && > > So the only impact of that rerere.enabled=false early is to make sure > we're not creating the .git/rr-cache. Not really. Unresolve is about recording the initial conflict in the index, so it is far easier to see its effect if you do not enable rerere, when you are manually debugging these earlier tests. And later test do check how it works with rerere enabled, but the way the original sequence of tests enable it is with the "mkdir". I.e. "if rerere.enabled is not set either way, presence of the directory means it is already enabled". The new test sequence uses the configuration variable explicitly, because in the new world order, the presence of the directory does not mean a thing.
On Mon, Jun 07 2021, Junio C Hamano wrote: > Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes: > >> On Sun, Jun 06 2021, Junio C Hamano wrote: >> >>> By default, the rerere machinery has been disabled since a bug in >>> the machinery could screw up the end user's data at the most >>> stressful time during the end user's workday (i.e. during conflict >>> resolution). >> >> What was that bug & in what commit was it fixed? Makes sense to note >> that here. > > There is no such bug ;-). > > Writing buggy code, not thinking about it carefully enough and > jumping up and down yelling this shiny new toy must be merged down > immediately is something we see on this list from others, but it is > the total opposite of how I operate. I just am extra cautious and > even after I am reasonably sure the code would not break, I prefer > to have volunteers to opt into testing. Thanks. I misread that, and was (perhaps mis-)remembering the previous thread about this discussing some past bugs... >> @@ -130,7 +129,6 @@ test_expect_success 'unmerge with plumbing' ' >> test_expect_success 'rerere and rerere forget' ' >> # from here on, use rerere. >> git config rerere.enabled true && >> - mkdir .git/rr-cache && >> prime_resolve_undo && >> echo record the resolution && >> git rerere && >> >> So the only impact of that rerere.enabled=false early is to make sure >> we're not creating the .git/rr-cache. > > Not really. Unresolve is about recording the initial conflict in > the index, so it is far easier to see its effect if you do not > enable rerere, when you are manually debugging these earlier tests. > > And later test do check how it works with rerere enabled, but the > way the original sequence of tests enable it is with the "mkdir". > I.e. "if rerere.enabled is not set either way, presence of the > directory means it is already enabled". The new test sequence > uses the configuration variable explicitly, because in the new world > order, the presence of the directory does not mean a thing. I mean you added "from here on, use rerere", but if I instrument the tests to set rerere.enabled=false they also pass, sans the .git/rr-cache directory being created. So we weren't "using rerere", we were just writing the data on the side. We *do* get a failure in test #3, "rm records reset clears", if we set rerere.autoUpdate=true. So it seems to me that what those first tests would benefit more from not having the addition of your rerere.enabled=false line early on. After all it's more interesting to test that the merge resolution is not different in any way under rerere.enabled=true & rerere.autoUpdate=false than to not write the rr-cache data at all. It seems like having just one test with rerere.enabled=false & "I did not write .git/rr-cache" would make for better coverage. I.e. this on top works: diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index 8c571ddf92..b010f504b0 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -46,11 +46,12 @@ prime_resolve_undo () { } test_expect_success setup ' - git config rerere.enabled false && mkdir fi && printf "a\0a" >binary && git add binary && + ! test_path_is_dir .git/rr-cache && test_commit initial fi/le first && + test_path_is_dir .git/rr-cache && git branch side && git branch another && printf "a\0b" >binary && @@ -128,9 +129,6 @@ test_expect_success 'unmerge with plumbing' ' ' test_expect_success 'rerere and rerere forget' ' - # from here on, use rerere. - git config rerere.enabled true && - mkdir .git/rr-cache && prime_resolve_undo && echo record the resolution && git rerere && @@ -156,7 +154,6 @@ test_expect_success 'rerere and rerere forget' ' test_expect_success 'rerere and rerere forget (subdirectory)' ' rm -fr .git/rr-cache && - mkdir .git/rr-cache && prime_resolve_undo && echo record the resolution && (cd fi && git rerere) && As an aside when testing this I found that I could make it segfault by not doing the mkdir() in setup_rerere() and without: diff --git a/rerere.c b/rerere.c index 83e740d730..06fb86d5b7 100644 --- a/rerere.c +++ b/rerere.c @@ -731,7 +731,10 @@ static void do_rerere_one_path(struct index_state *istate, /* Has the user resolved it already? */ if (variant >= 0) { if (!handle_file(istate, path, NULL, NULL)) { - copy_file(rerere_path(id, "postimage"), path, 0666); + const char *dst = rerere_path(id, "postimage"); + if (copy_file(dst, path, 0666)) + die_errno(_("could not copy '%s' to '%s'"), + path, dst); id->collection->status[variant] |= RR_HAS_POSTIMAGE; fprintf_ln(stderr, _("Recorded resolution for '%s'."), path); free_rerere_id(rr_item); I.e. we make the hard assumption that the directory has been created, and don't check the return value(s) of various subsequent file copying etc. So there's a rare segfault in the wild if the "setup_rerere()" races with something that removes the .git/rr-cache (perhaps git-gc will remove it entirely?).
Junio C Hamano wrote: > By default, the rerere machinery has been disabled since a bug in > the machinery could screw up the end user's data at the most > stressful time during the end user's workday (i.e. during conflict > resolution). > > It however has been in wide use without causing much trouble (other > than, obviously, replaying a broken conflict resolution that was > recorded earlier when the user made a mismerge), and it is about > time to enable it by default. That is a good diea. > Signed-off-by: Junio C Hamano <gitster@pobox.com> But did you really come up with it all by yourself? Could perhaps this mail [1] sent 5 days prior have anything to do with it? > If the defaults make your life hard, then shouldn't we change the > defaults? > But, if we are already on this topic... who wants rerere disabled by > default? Cheers. [1] https://lore.kernel.org/git/60b61089ba63d_e40ca20894@natae.notmuch/
diff --git a/Documentation/config/rerere.txt b/Documentation/config/rerere.txt index 40abdf6a6b..45e97fc0fa 100644 --- a/Documentation/config/rerere.txt +++ b/Documentation/config/rerere.txt @@ -7,6 +7,5 @@ rerere.enabled:: Activate recording of resolved conflicts, so that identical conflict hunks can be resolved automatically, should they be encountered again. By default, linkgit:git-rerere[1] is - enabled if there is an `rr-cache` directory under the - `$GIT_DIR`, e.g. if "rerere" was previously used in the - repository. + enabled, but this configuration can be set to 'false' to + turn it off. diff --git a/rerere.c b/rerere.c index d83d58df4f..83e740d730 100644 --- a/rerere.c +++ b/rerere.c @@ -18,8 +18,7 @@ #define THREE_STAGED 2 void *RERERE_RESOLVED = &RERERE_RESOLVED; -/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */ -static int rerere_enabled = -1; +static int rerere_enabled = 1; /* default to true */ /* automatically update cleanly resolved paths to the index */ static int rerere_autoupdate; @@ -852,16 +851,11 @@ static GIT_PATH_FUNC(git_path_rr_cache, "rr-cache") static int is_rerere_enabled(void) { - int rr_cache_exists; - if (!rerere_enabled) return 0; - rr_cache_exists = is_directory(git_path_rr_cache()); - if (rerere_enabled < 0) - return rr_cache_exists; - - if (!rr_cache_exists && mkdir_in_gitdir(git_path_rr_cache())) + if (!is_directory(git_path_rr_cache()) && + mkdir_in_gitdir(git_path_rr_cache())) die(_("could not create directory '%s'"), git_path_rr_cache()); return 1; } diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index be6c84c52a..8c571ddf92 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -46,6 +46,7 @@ prime_resolve_undo () { } test_expect_success setup ' + git config rerere.enabled false && mkdir fi && printf "a\0a" >binary && git add binary && @@ -127,6 +128,8 @@ test_expect_success 'unmerge with plumbing' ' ' test_expect_success 'rerere and rerere forget' ' + # from here on, use rerere. + git config rerere.enabled true && mkdir .git/rr-cache && prime_resolve_undo && echo record the resolution &&
By default, the rerere machinery has been disabled since a bug in the machinery could screw up the end user's data at the most stressful time during the end user's workday (i.e. during conflict resolution). It however has been in wide use without causing much trouble (other than, obviously, replaying a broken conflict resolution that was recorded earlier when the user made a mismerge), and it is about time to enable it by default. Signed-off-by: Junio C Hamano <gitster@pobox.com> --- Documentation/config/rerere.txt | 5 ++--- rerere.c | 12 +++--------- t/t2030-unresolve-info.sh | 3 +++ 3 files changed, 8 insertions(+), 12 deletions(-)