{"thread":{"id":"64136","subject":"The case of `git update-ref MERGE_HEAD`","startedAt":"2025-09-12T16:20:02Z","lastAt":"2025-09-15T12:16:39Z","messageCount":2,"participants":["Johannes Sixt","Patrick Steinhardt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"526200","messageId":"c9794ca2-0822-485f-a10f-6ecefa7275d1@kdbg.org","threadId":"64136","inReplyTo":null,"subject":"The case of `git update-ref MERGE_HEAD`","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2025-09-12T16:19:52Z","receivedAt":"2025-09-12T16:20:02Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"When I commit a merge, the commit message shows this advice:\n\n# It looks like you may be committing a merge.\n# If this is not correct, please run\n#       git update-ref -d MERGE_HEAD\n# and try again.\n\nHowever, when I follow the advice, I get this error:\n\n$ git update-ref -d MERGE_HEAD\nerror: refusing to update pseudoref 'MERGE_HEAD'\n\nAlso, I found a use case to set MERGE_HEAD to a particular commit, but I\ncan't do that, either:\n\n$ git update-ref MERGE_HEAD e9c115e666fd6a3faaf187f5d145b32861a45cc8\nfatal: update_ref failed for ref 'MERGE_HEAD': refusing to update pseudoref 'MERGE_HEAD'\n\nI know I can do\n\n$ echo e9c115e666fd6a3faaf187f5d145b32861a45cc8 > .git/MERGE_HEAD\n\nin the primary worktree. But I needed to do this in a secondary\nworktree, where this is more like\n\n$ echo e9c115e666fd6a3faaf187f5d145b32861a45cc8 \\\n     > \"$(git rev-parse --git-dir)\"/MERGE_HEAD\n\nwhich is a bit unwieldy...\n\n8e4f5c2dc26e (\"refs: refuse to write pseudorefs\", 2024-05-15) removed\nthe ability to wrangle pseudo-refs with `git update-ref`. Much earlier,\nb6d2558c9ea3 (\"builtin/commit: suggest update-ref for pseudoref\nremoval\", 2020-08-21) changed the commit message template with the\njustification:\n\n> [S]uggest a \"update-ref -d\" command, which will work regardless of\n> ref storage backend.\n\nLooks like we couldn't uphold the promise. Any suggestions?\n\n-- Hannes\n\n"},{"id":"526357","messageId":"aMgDoGFy84EenCHF@pks.im","threadId":"64136","inReplyTo":"c9794ca2-0822-485f-a10f-6ecefa7275d1@kdbg.org","subject":"Re: The case of `git update-ref MERGE_HEAD`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T12:16:32Z","receivedAt":"2025-09-15T12:16:39Z","isPatch":false,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 12, 2025 at 06:19:52PM +0200, Johannes Sixt wrote:\n> When I commit a merge, the commit message shows this advice:\n> \n> # It looks like you may be committing a merge.\n> # If this is not correct, please run\n> #       git update-ref -d MERGE_HEAD\n> # and try again.\n> \n> However, when I follow the advice, I get this error:\n> \n> $ git update-ref -d MERGE_HEAD\n> error: refusing to update pseudoref 'MERGE_HEAD'\n> \n> Also, I found a use case to set MERGE_HEAD to a particular commit, but I\n> can't do that, either:\n> \n> $ git update-ref MERGE_HEAD e9c115e666fd6a3faaf187f5d145b32861a45cc8\n> fatal: update_ref failed for ref 'MERGE_HEAD': refusing to update pseudoref 'MERGE_HEAD'\n> \n> I know I can do\n> \n> $ echo e9c115e666fd6a3faaf187f5d145b32861a45cc8 > .git/MERGE_HEAD\n> \n> in the primary worktree. But I needed to do this in a secondary\n> worktree, where this is more like\n> \n> $ echo e9c115e666fd6a3faaf187f5d145b32861a45cc8 \\\n>      > \"$(git rev-parse --git-dir)\"/MERGE_HEAD\n> \n> which is a bit unwieldy...\n> \n> 8e4f5c2dc26e (\"refs: refuse to write pseudorefs\", 2024-05-15) removed\n> the ability to wrangle pseudo-refs with `git update-ref`. Much earlier,\n> b6d2558c9ea3 (\"builtin/commit: suggest update-ref for pseudoref\n> removal\", 2020-08-21) changed the commit message template with the\n> justification:\n> \n> > [S]uggest a \"update-ref -d\" command, which will work regardless of\n> > ref storage backend.\n> \n> Looks like we couldn't uphold the promise. Any suggestions?\n\nThe best we can do is to special-case pseudorefs in relevant code paths.\nBut we have to be very careful with how exactly we do that. Pseudorefs\naren't real refs, so we for example do not want to add logic to update\nthem in the same transaction as normal references.\n\nBut for something like git-update-ref(1) we may specifically carve out a\nway to delete and update a single pseudoref and then handle this outside\nof the normal ref transaction logic.\n\nPatrick\n"}]}