{"thread":{"id":"60590","subject":"What's the recommendation for forgetting all rerere's records?","startedAt":"2023-12-06T22:58:16Z","lastAt":"2024-02-10T17:20:08Z","messageCount":7,"participants":["Sean Allred","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"485404","messageId":"m0y1e7kkft.fsf@epic96565.epic.com","threadId":"60590","inReplyTo":null,"subject":"What's the recommendation for forgetting all rerere's records?","fromName":"Sean Allred","fromEmail":"allred.sean@gmail.com","sentAt":"2023-12-06T22:37:23Z","receivedAt":"2023-12-06T22:58:16Z","isPatch":false,"sender":{"key":"allred.sean@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2082195?v=4"},"body":"Hi all,\n\nWhen outside the context of a conflict (no rebase/merge in progress),\nwhat's the intended workflow to clear out the contents of\n$GIT_DIR/rr-cache?\n\nWe have developers who'd like to discard their faulty resolutions after\ncompleting a rebase gone awry (but not aborted). There doesn't seem to\nbe a recommendation in git-rerere(1) for how to deal with this\nsituation. (git-rerere-forget seems to only work in the context of an\nactive conflict -- and is documented as such.)\n\nI'm wary of recommending `rm -rf \"$(git rev-parse --git-dir)/rr-cache\"`\n-- it's hard to describe this as anything but hacky when the rest of the\nexperience is handled in porcelain.\n\nThanks!\n\n--\nSean Allred\n"},{"id":"485497","messageId":"xmqqcyvgz3ih.fsf@gitster.g","threadId":"60590","inReplyTo":"m0y1e7kkft.fsf@epic96565.epic.com","subject":"Re: What's the recommendation for forgetting all rerere's records?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-12-08T23:19:18Z","receivedAt":"2023-12-08T23:19:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sean Allred <allred.sean@gmail.com> writes:\n\n> When outside the context of a conflict (no rebase/merge in progress),\n> what's the intended workflow to clear out the contents of\n> $GIT_DIR/rr-cache?\n\nYou could \"rm -fr .git/rr-cache/??*\" if you want.\n\nThe \"intended\" workflow is there will no need to \"clear out\" at all;\nyou may notice mistaken resolution, and you will remove it when you\nnotice one, but the bulk of the remaining database entries ought to\nbe still correct.\n"},{"id":"485715","messageId":"m0sf43abw7.fsf@epic96565.epic.com","threadId":"60590","inReplyTo":"xmqqcyvgz3ih.fsf@gitster.g","subject":"Re: What's the recommendation for forgetting all rerere's records?","fromName":"Sean Allred","fromEmail":"allred.sean@gmail.com","sentAt":"2023-12-15T12:21:36Z","receivedAt":"2023-12-15T12:27:55Z","isPatch":false,"sender":{"key":"allred.sean@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2082195?v=4"},"body":"\nJunio C Hamano <gitster@pobox.com> writes:\n> Sean Allred <allred.sean@gmail.com> writes:\n>> When outside the context of a conflict (no rebase/merge in progress),\n>> what's the intended workflow to clear out the contents of\n>> $GIT_DIR/rr-cache?\n>\n> You could \"rm -fr .git/rr-cache/??*\" if you want.\n\nHere's my reasoning for not wanting that:\n\n>> I'm wary of recommending `rm -rf \"$(git rev-parse --git-dir)/rr-cache\"`\n>> -- it's hard to describe this as anything but hacky when the rest of the\n>> experience is handled in porcelain.\n\n> The \"intended\" workflow is there will no need to \"clear out\" at all;\n> you may notice mistaken resolution, and you will remove it when you\n> notice one, but the bulk of the remaining database entries ought to\n> be still correct.\n\nWhen we noticed mistaken resolutions, rerere had already applied the\nrecorded resolution and there was no apparent way to return to the\nconflicted state. If clearing out the rerere database was never an\nintended workflow here, maybe _that's_ my actual question?\n\nIt seems likely this 'recovery' workflow should just be documented in\ngit-rerere.txt (which I'm happy to take on once I learn what that\nworkflow should be).\n\n--\nSean Allred\n"},{"id":"485719","messageId":"xmqqa5qbmnrm.fsf@gitster.g","threadId":"60590","inReplyTo":"m0sf43abw7.fsf@epic96565.epic.com","subject":"Re: What's the recommendation for forgetting all rerere's records?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-12-15T16:30:37Z","receivedAt":"2023-12-15T16:33:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sean Allred <allred.sean@gmail.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>> Sean Allred <allred.sean@gmail.com> writes:\n>>> When outside the context of a conflict (no rebase/merge in progress),\n>>> what's the intended workflow to clear out the contents of\n>>> $GIT_DIR/rr-cache?\n>>\n>> You could \"rm -fr .git/rr-cache/??*\" if you want.\n>\n> Here's my reasoning for not wanting that:\n>\n>>> I'm wary of recommending `rm -rf \"$(git rev-parse --git-dir)/rr-cache\"`\n>>> -- it's hard to describe this as anything but hacky when the rest of the\n>>> experience is handled in porcelain.\n\nIt is meant to be ugly ;-); the reason why the Porcelain does not\noffer bulk erasure is because we want to strongly discourage it.\n\n>> The \"intended\" workflow is there will no need to \"clear out\" at all;\n>> you may notice mistaken resolution, and you will remove it when you\n>> notice one, but the bulk of the remaining database entries ought to\n>> be still correct.\n>\n> When we noticed mistaken resolutions, rerere had already applied the\n> recorded resolution and there was no apparent way to return to the\n> conflicted state.\n\nThe simplest is to go back to the original state before the merge\nand then redo the operation without rerere enabled.\n\n    $ git reset --hard\n    $ git -c rerere.enabled=no merge <whatever arguments you used>\n\nAnd you can redo the merge manually.\n\nBut more generally, after you incorrectly resolved a merge conflict,\nwhether you fumbled with your editor yourself or you let rerere kick\nin to reuse your recorded resolution that you made in the past that\nwas faulty, before or after you run \"git add\" to tell the resolution\nto the index, you should be able to do\n\n    $ git checkout --merge <pathspec>\n\nto tell Git to \"unresolve\" such paths.  Here is the relevant\nparagraph from the \"git checkout --help\":\n\n    When checking out paths from the index, this option lets you recreate the\n    conflicted merge in the specified paths. This option cannot be used when\n    checking out paths from a tree-ish.\n\nThe below is what I just did to demonstrate.  You can try the same\nif you have our source code.  The first attempt will likely to\nconflict because you do not have the rerere record, but you can\nresolve the conflict in builtin/mv.c the way I did (shown by first\n\"git diff\" in the sample transcript), and run \"git rerere\" (or just\n\"git commit -a\" should also work) to record the resolution, and then\n\"git reset --hard\" to obtain a sample rerere record you can use to\npractice.\n\n    # Just a sample merge I know will have a conflict\n    $ SAMPLE=a59dbae0b3bd; # v2.43.0-rc0~126\n\n    # Go to its parent and retry the merge with its second parent\n    $ git checkout --detach $SAMPLE^1\n    $ git merge $SAMPLE^2\n    Auto-merging builtin/mv.c\n    CONFLICT (content): Merge conflict in builtin/mv.c\n    Resolved 'builtin/mv.c' using previous resolution.\n    Automatic merge failed; fix conflicts and then commit the result.\n\n    # We have conflict, and rerere kicked in.  Because I do not have\n    # rerere.autoupdate configuration set, I can as \"ls-files -u\"\n    # which paths are conflicting, but that is unnecessary (we\n    # can see the path with conflict with the CONFLICT label above).\n    $ git ls-files -u\n    100644 665bd274485f6c76403e9230539e2650073a47f3 1\tbuiltin/mv.c\n    100644 05e7156034e04d637990cabf105f7fa967b0f2aa 2\tbuiltin/mv.c\n    100644 80fc7a3c7029603a0fcaf9d15d8432ed799b4909 3\tbuiltin/mv.c\n\n    # This is the resolution \"rerere\" gave me, which is what I did\n    # back in August this year.  If you are following this example,\n    # you'll first have to edit builtin/mv.c to hand resolve,\n    # register the resolution to \"rerere\" database, and then run\n    # \"git reset --hard\" to go back to the state before you did the\n    # \"git merge $SAMPLE^2\" step to repeat.\n    $ git diff\n    diff --cc builtin/mv.c\n    index 05e7156034,80fc7a3c70..0000000000\n    --- i/builtin/mv.c\n    +++ w/builtin/mv.c\n    @@@ -304,8 -303,8 +304,8 @@@ int cmd_mv(int argc, const char **argv\n                            goto act_on_entry;\n                    }\n                    if (S_ISDIR(st.st_mode)\n     -\t\t    && lstat(dst, &st) == 0) {\n     +\t\t    && lstat(dst, &dest_st) == 0) {\n    - \t\t\tbad = _(\"cannot move directory over file\");\n    + \t\t\tbad = _(\"destination already exists\");\n                            goto act_on_entry;\n                    }\n\n    # Now the fun command you seem to have missed.  You MUST give\n    # \"git checkout --merge\" a pathspec.  I do not encourage it but\n    # using \".\" to say \"unresolve everything under the sun\" should\n    # also work.\n    $ git checkout --merge builtin/mv.c\n    Recreated 1 merge conflict\n\n    # Let's check the result.  We have recreated the conflicted\n    # state in the working tree.\n    $ git diff\n    diff --cc builtin/mv.c\n    index 05e7156034,80fc7a3c70..0000000000\n    --- i/builtin/mv.c\n    +++ w/builtin/mv.c\n    @@@ -304,8 -303,8 +304,16 @@@ int cmd_mv(int argc, const char **argv\n                            goto act_on_entry;\n                    }\n                    if (S_ISDIR(st.st_mode)\n    ++<<<<<<< ours\n     +\t\t    && lstat(dst, &dest_st) == 0) {\n     +\t\t\tbad = _(\"cannot move directory over file\");\n    ++||||||| base\n    ++\t\t    && lstat(dst, &st) == 0) {\n    ++\t\t\tbad = _(\"cannot move directory over file\");\n    ++=======\n    + \t\t    && lstat(dst, &st) == 0) {\n    + \t\t\tbad = _(\"destination already exists\");\n    ++>>>>>>> theirs\n                            goto act_on_entry;\n                    }\n\n    # You should then be able to correct the resolution with your\n    # editor.\n    $ edit builtin/mv.c\n\n    # If this is one-time fix (you are happy with the original\n    # resolution and wanted to deviate from it only once this time),\n    # there is nothing else need to be done.  If you want to record\n    # this as a new resolution, you'd get rid of the old one and\n    # record this one.\n    $ git rerere forget builtin/mv.c\n    $ git rerere\n\n\n\n"},{"id":"486246","messageId":"m0frzeu89w.fsf@epic96565.epic.com","threadId":"60590","inReplyTo":"35f24a01d15ce28932bb6be098d6a164a49cc542008f75673cd6221a9b24b578@mu.id","subject":"Re: What's the recommendation for forgetting all rerere's records?","fromName":"Sean Allred","fromEmail":"allred.sean@gmail.com","sentAt":"2024-01-03T08:30:45Z","receivedAt":"2024-01-03T08:32:31Z","isPatch":false,"sender":{"key":"allred.sean@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2082195?v=4"},"body":"\n(Doesn't look like this actually got picked up by lore when I originally\nsent it at Fri, 22 Dec 2023 12:19:50 -0600. This is a re-send; apologies\nif you get this message twice.)\n\n==\n\nThere might be a bug here.\n\nJunio C Hamano <gitster@pobox.com> writes:\n     # Now the fun command you seem to have missed.  You MUST give\n     # \"git checkout --merge\" a pathspec.  I do not encourage it but\n     # using \".\" to say \"unresolve everything under the sun\" should\n     # also work.\n     $ git checkout --merge builtin/mv.c\n     Recreated 1 merge conflict\n\nYep, I definitely missed this! Very handy, thank you :-)\n\n     # You should then be able to correct the resolution with your\n     # editor.\n     $ edit builtin/mv.c\n\n     # If this is one-time fix (you are happy with the original\n     # resolution and wanted to deviate from it only once this time),\n     # there is nothing else need to be done.  If you want to record\n     # this as a new resolution, you'd get rid of the old one and\n     # record this one.\n     $ git rerere forget builtin/mv.c\n     $ git rerere\n\nIt's taken some time to investigate on our end, but it appears that the\nissue we're seeing is particular to git-rebase.\n\nConsider a run using git-merge, which works perfectly as you describe:\n\n    # Let's set up our conflict; most output here elided for brevity.\n    $ git init\n    $ echo aaa >file\n    $ git add file\n    $ git commit -ambase\n    $ git branch feature\n    $ echo bbb >file\n    $ git commit -amremote\n    $ git switch feature\n    $ echo ccc >file\n    $ git commit -amlocal\n    $ git --no-pager log --oneline --graph --all\n    * 6b33f42 (HEAD -> feature) local\n    | * 7e189f6 (main) remote\n    |/\n    * c5901f5 base\n\n    # Now for the fun part!\n    $ git config rerere.enabled true\n\n    $ git merge main\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    Recorded preimage for 'file'\n    Automatic merge failed; fix conflicts and then commit the result.\n\n    $ echo 'bad merge' >file\n    $ git commit -ammerge\n    Recorded resolution for 'file'.\n    [feature 75d45f0] merge\n\n    # Ack! That merge was bad. Let's try that again.\n    $ git reset --hard @^\n    HEAD is now at 6b33f42 local\n\n    $ git merge main\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    Resolved 'file' using previous resolution.\n    Automatic merge failed; fix conflicts and then commit the result.\n\n    # Your method to correct this single bad merge works flawlessly:\n    $ git checkout --merge file\n    Recreated 1 merge conflict\n\n    $ git rerere forget file\n    Updated preimage for 'file'\n    Forgot resolution for 'file'\n\n    $ echo 'good merge' >file\n\n    $ git commit -ammerge\n    Recorded resolution for 'file'.\n    [feature 1770541] merge\n\nLet's compare this with git-rebase:\n\n    # Same setup as before\n    $ git init\n    $ echo aaa >file\n    $ git add file\n    $ git commit -ambase\n    $ git branch feature\n    $ echo bbb >file\n    $ git commit -amremote\n    $ git switch feature\n    $ echo ccc >file\n    $ git commit -amlocal\n    $ git --no-pager log --oneline --graph --all\n    * b4d7aeb (HEAD -> feature) local\n    | * 2a0978d (main) remote\n    |/\n    * 91140a6 base\n\n    # Now for the fun part! Just like before, but we're going to use\n    # git-rebase instead of git-merge.\n    $ git config rerere.enabled true\n\n    $ git rebase main\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    error: could not apply b4d7aeb... local\n    hint: Resolve all conflicts manually, mark them as resolved with\n    hint: \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n    hint: You can instead skip this commit: run \"git rebase --skip\".\n    hint: To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n    Recorded preimage for 'file'\n    Could not apply b4d7aeb... local\n\n    $ echo 'bad merge' >file\n    $ git add file\n\n    $ EDITOR=: git rebase --continue\n    file: needs merge\n    You must edit all merge conflicts and then\n    mark them as resolved using git add\n\n    $ git rebase --abort\n\n    $ git rebase main\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    error: could not apply b4d7aeb... local\n    hint: Resolve all conflicts manually, mark them as resolved with\n    hint: \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n    hint: You can instead skip this commit: run \"git rebase --skip\".\n    hint: To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n    Recorded preimage for 'file'\n    Could not apply b4d7aeb... local\n\n    $ git checkout --merge .\n    Recreated 1 merge conflict\n\n    $ git rerere forget .\n    error: no remembered resolution for 'file'\n\n    $ echo 'good merge' >file\n\n    $ EDITOR=: git rebase --continue\n    file: needs merge\n    You must edit all merge conflicts and then\n    mark them as resolved using git add\n\nIs this a bug?\n\n--\nSean Allred\n"},{"id":"486251","messageId":"m05y0au2od.fsf@epic96565.epic.com","threadId":"60590","inReplyTo":"m0frzeu89w.fsf@epic96565.epic.com","subject":"Re: What's the recommendation for forgetting all rerere's records?","fromName":"Sean Allred","fromEmail":"allred.sean@gmail.com","sentAt":"2024-01-03T09:27:51Z","receivedAt":"2024-01-03T10:33:25Z","isPatch":false,"sender":{"key":"allred.sean@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2082195?v=4"},"body":"\nThere was enough going on with that prior email that I gave it another\nlook and found some errors.\n\n>     $ echo 'bad merge' >file\n>     $ git add file\n>\n>     $ EDITOR=: git rebase --continue\n>     file: needs merge\n>     You must edit all merge conflicts and then\n>     mark them as resolved using git add\n>\n>     $ git rebase --abort\n>\n>     $ git rebase main\n>     Auto-merging file\n>     CONFLICT (content): Merge conflict in file\n>     error: could not apply b4d7aeb... local\n>     hint: Resolve all conflicts manually, mark them as resolved with\n>     hint: \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n>     hint: You can instead skip this commit: run \"git rebase --skip\".\n>     hint: To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n>     Recorded preimage for 'file'\n>     Could not apply b4d7aeb... local\n>\n>     $ git checkout --merge .\n>     Recreated 1 merge conflict\n>\n>     $ git rerere forget .\n>     error: no remembered resolution for 'file'\n>\n>     $ echo 'good merge' >file\n>\n>     $ EDITOR=: git rebase --continue\n>     file: needs merge\n>     You must edit all merge conflicts and then\n>     mark them as resolved using git add\n\nThis section should have read:\n\n    $ echo 'bad merge' >file\n    $ git add file\n\n    $ EDITOR=: git rebase --continue\n    Recorded resolution for 'file'.\n    [detached HEAD 5e3c431] local\n     1 file changed, 1 insertion(+), 1 deletion(-)\n    Successfully rebased and updated refs/heads/feature.\n\n    $ git reset --hard @{1}\n    HEAD is now at b4d7aeb local\n\n    $ git rebase main\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    error: could not apply b4d7aeb... local\n    hint: Resolve all conflicts manually, mark them as resolved with\n    hint: \"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n    hint: You can instead skip this commit: run \"git rebase --skip\".\n    hint: To abort and get back to the state before \"git rebase\", run \"git rebase --abort\".\n    Resolved 'file' using previous resolution.\n    Could not apply b4d7aeb... local\n\n    $ git checkout --merge .\n    Recreated 1 merge conflict\n\n    $ git rerere forget .\n    error: no remembered resolution for 'file'\n\nI've driven myself a little nuts trying to reproduce it this morning,\nbut in doing so I've come to an important discovery: this bug presents\nif `core.autocrlf=true` but does *not* present if `core.autocrlf=input`.\n\nFor completeness and future reference, the following script reproduces\nthe issue on Windows:\n\n    git init\n    echo aaa >file\n    git add file\n    git commit -ambase\n    git branch feature\n    echo bbb >file\n    git commit -amremote\n    git switch feature\n    echo ccc >file\n    git commit -amlocal\n    git config rerere.enabled true\n    git config core.autocrlf true     # <--\n\n    # setup complete; let's rebase!\n    git rebase main\n    echo 'bad merge' >file\n    git add file\n    EDITOR=: git rebase --continue\n\n    # uh oh; that was a bad resolution; let's try again\n    git reset --hard @{1}\n    git rebase main\n    git checkout --merge .\n    git rerere forget .               # fails\n    echo 'good merge' >file\n    git add file\n    EDITOR=: git rebase --continue\n\nAt the end of this script, the 'bad merge' is still the recorded\nresolution and no rerere record exists for the 'good merge'.\n\nJust in case there's another piece of config somehow relevant, here's a\ndump of the system that reproduced this:\n\n    $ git config --list --show-scope | sort\n    global\tuser.email=[clip]\n    global\tuser.name=[clip]\n    local\tcore.autocrlf=true\n    local\tcore.bare=false\n    local\tcore.filemode=false\n    local\tcore.ignorecase=true\n    local\tcore.logallrefupdates=true\n    local\tcore.repositoryformatversion=0\n    local\tcore.symlinks=false\n    local\trerere.enabled=true\n    system\tcore.autocrlf=input\n    system\tcore.fscache=true\n    system\tcore.fsmonitor=true\n    system\tcore.symlinks=false\n    system\tcredential.helper=manager\n    system\tcredential.https://dev.azure.com.usehttppath=true\n    system\tdiff.astextplain.textconv=astextplain\n    system\tfilter.lfs.clean=git-lfs clean -- %f\n    system\tfilter.lfs.process=git-lfs filter-process\n    system\tfilter.lfs.required=true\n    system\tfilter.lfs.smudge=git-lfs smudge -- %f\n    system\thttp.sslbackend=schannel\n    system\thttp.sslcainfo=C:/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt\n    system\tinit.defaultbranch=main\n    system\tpull.rebase=true\n\n    $ git --version\n    git version 2.43.0.windows.1\n\nIt's worth noting at this point that while I believe I reproduced on\nmacOS last week, that doesn't jive with the available evidence (and I\ncan't reproduce it on macOS this morning, though I suspect that has more\nto do with native use of LF over CRLF than anything else).\n\n--\nSean Allred\n"},{"id":"488358","messageId":"m01q9k9qyh.fsf@epic96565.epic.com","threadId":"60590","inReplyTo":"m05y0au2od.fsf@epic96565.epic.com","subject":"Re: What's the recommendation for forgetting all rerere's records?","fromName":"Sean Allred","fromEmail":"allred.sean@gmail.com","sentAt":"2024-02-10T17:18:45Z","receivedAt":"2024-02-10T17:20:08Z","isPatch":false,"sender":{"key":"allred.sean@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2082195?v=4"},"body":"\nSean Allred <allred.sean@gmail.com> writes:\n\n> I've driven myself a little nuts trying to reproduce it this morning,\n> but in doing so I've come to an important discovery: this bug presents\n> if `core.autocrlf=true` but does *not* present if `core.autocrlf=input`.\n>\n> For completeness and future reference, the following script reproduces\n> the issue on Windows:\n>\n>     [clip]\n>\n> At the end of this script, the 'bad merge' is still the recorded\n> resolution and no rerere record exists for the 'good merge'.\n>\n> Just in case there's another piece of config somehow relevant, here's a\n> dump of the system that reproduced this:\n>\n>     [clip]\n>\n> It's worth noting at this point that while I believe I reproduced on\n> macOS last week, that doesn't jive with the available evidence (and I\n> can't reproduce it on macOS this morning, though I suspect that has more\n> to do with native use of LF over CRLF than anything else).\n\nIs there a good way to convert this to a proper bug report without\nlosing the context?\n\n--\nSean Allred\n"}]}