{"thread":{"id":"63378","subject":"Bug Report or Unexpected Feature when \"git restore -m .\" restores merge conflicted state of a file after a commit","startedAt":"2025-04-30T21:03:55Z","lastAt":"2025-04-30T21:39:07Z","messageCount":2,"participants":["Terry Bear","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"517034","messageId":"CAJt5hUyLoNfEbQe4wpES8AZP5yimos+xjqU9B4PszGxMrg50jg@mail.gmail.com","threadId":"63378","inReplyTo":null,"subject":"Bug Report or Unexpected Feature when \"git restore -m .\" restores merge conflicted state of a file after a commit","fromName":"Terry Bear","fromEmail":"terrythebear746@gmail.com","sentAt":"2025-04-30T21:03:12Z","receivedAt":"2025-04-30T21:03:55Z","isPatch":false,"sender":{"key":"terrythebear746@gmail.com","avatar":null},"body":"What did you do before the bug happened? (Steps to reproduce your issue)\n\nCan be replicated on a new repository.\n\n1. Initialize git repo.\n    git init\n2. Create a file\n    touch test-file\n3. Write to the file\n    \"update 1\"\n4. Stage the changes to the file, create a commit.\n    git add .\n    git commit -m \"update 1\"\n5. Copy the branch\n    git branch -c \"main-copy\"\n6. Write to the file on the same first \"main\" branch by appending new\ncontent on the second line of the \"test-file\"\n    \"update 2\"\n   The file looks like:\n    \"update 1\"\n    \"update 2\"\n7. Stage and commit.\n    git commit -a -m \"update 2\"\n8. Introduce another change to the file but keep it on the work-space\nby appending another line\n    \"update 3\"\n   The file looks like:\n    \"update 1\"\n    \"update 2\"\n    \"update 3\"\n9. Make a merge switch\n    git switch --merge main-copy\n   The file on the \"main-copy\" branch should look like:\n     \"update 1\"\n     \"<<<<<<< main-copy\"\n     \"=======\"\n     \"update 2\"\n     \"update 3\"\n     \">>>>>>> local\"\n10. Stage and commit file\n    git commit -a -m \"merge conflict on main-copy\"\n11. Restore merge-conflicted state\n    git restore -m .\n\nWhat did you expect to happen? (Expected behavior)\nThe \"git restore -m .\" is not supposed to restore the merge-conflicted\nstate of the file after it was staged and committed\n\nWhat happened instead? (Actual behavior)\nThe \"git restore -m .\" restored the merge-conflicted state of the file\nafter it was staged and committed\n\nWhat's different between what you expected and what actually happened?\nThe restoration of the merge-conflicted state of the file after it was\nstaged and committed\n\nAnything else you want to add:\nI am not sure whether it is a bug or a feature but the behavior seemed\nunexpected and I couldn't find any mentions of it.\n\n[System Info]\ngit version:\ngit version 2.34.1\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nuname: Linux 6.8.0-57-generic #59~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC\nWed Mar 19 17:07:41 UTC 2 x86_64\ncompiler info: gnuc: 11.4\nlibc info: glibc: 2.35\n$SHELL (typically, interactive shell): /bin/bash\n\n\n[Enabled Hooks]\nnot run from a git repository - no hooks to show\n"},{"id":"517035","messageId":"xmqqzffxz5vr.fsf@gitster.g","threadId":"63378","inReplyTo":"CAJt5hUyLoNfEbQe4wpES8AZP5yimos+xjqU9B4PszGxMrg50jg@mail.gmail.com","subject":"Re: Bug Report or Unexpected Feature when \"git restore -m .\" restores merge conflicted state of a file after a commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-30T21:39:04Z","receivedAt":"2025-04-30T21:39:07Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Terry Bear <terrythebear746@gmail.com> writes:\n\n> 9. Make a merge switch\n>     git switch --merge main-copy\n>    The file on the \"main-copy\" branch should look like:\n>      \"update 1\"\n>      \"<<<<<<< main-copy\"\n>      \"=======\"\n>      \"update 2\"\n>      \"update 3\"\n>      \">>>>>>> local\"\n> 10. Stage and commit file\n>     git commit -a -m \"merge conflict on main-copy\"\n> 11. Restore merge-conflicted state\n>     git restore -m .\n>\n> What did you expect to happen? (Expected behavior)\n> The \"git restore -m .\" is not supposed to restore the merge-conflicted\n> state of the file after it was staged and committed\n\nJust a quick question.  If you did \"git reset --hard\" between steps\n10 and 11, does the outcome change?\n\nI think the behaviour you observed dates back to the very original\nimplementation of the feature, made in cfc5789a (resolve-undo:\nrecord resolved conflicts in a new index extension section,\n2009-12-25).\n\n    resolve-undo: record resolved conflicts in a new index extension section\n    \n    When resolving a conflict using \"git add\" to create a stage #0 entry, or\n    \"git rm\" to remove entries at higher stages, remove_index_entry_at()\n    function is eventually called to remove unmerged (i.e. higher stage)\n    entries from the index.  Introduce a \"resolve_undo_info\" structure and\n    keep track of the removed cache entries, and save it in a new index\n    extension section in the index_state.\n    \n    Operations like \"read-tree -m\", \"merge\", \"checkout [-m] <branch>\" and\n    \"reset\" are signs that recorded information in the index is no longer\n    necessary.  The data is removed from the index extension when operations\n    start; they may leave conflicted entries in the index, and later user\n    actions like \"git add\" will record their conflicted states afresh.\n\nNotice that \"git add\" or \"git commit -a\" are not included in the\noperations that are signs that the previous conflicted state no\nlonger needs to be recreatable?  In other words, it is part of the\ndesign that you can take back the conflicted state across \"git add\"\nor \"git commit\", because you will thank Git later when you realize\nthat your resolution was broken and you want to redo it after you\nfinished your step #10.\n\nIf you do not want to restore the conflicted state, don't do \"git\nrestore -m .\" at that point ;-).\n\n\n"}]}