{"thread":{"id":"61260","subject":"git-merge: --no-commit is not respected on a fresh repository","startedAt":"2024-04-03T13:28:05Z","lastAt":"2024-04-03T17:29:25Z","messageCount":2,"participants":["Jasmin Oster","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"492158","messageId":"22efe19e-de44-4b6d-8e8b-57e2bddb321e@anexia.com","threadId":"61260","inReplyTo":null,"subject":"git-merge: --no-commit is not respected on a fresh repository","fromName":"Jasmin Oster","fromEmail":"joster@anexia.com","sentAt":"2024-04-03T13:26:53Z","receivedAt":"2024-04-03T13:28:05Z","isPatch":false,"sender":{"key":"joster@anexia.com","avatar":null},"body":"## What did you do before the bug happened? (Steps to reproduce your issue)\n\nWhen trying to perform a subtree merge, especially following the blog \npost on https://nuclearsquid.com/writings/subtree-merging-and-you/,\nI noticed that Git does not respect the --no-commit option if the \nrepository does not have a history.\n\n1. Create a new repository: $ git init\n2. Add a remote: $ git remote add foo ../<path-to-another-repo>\n3. Fetch everything: $ git fetch --all\n4. Initiate a subtree merge: $ git merge -s our --no-commit foo/main\n\n## What did you expect to happen? (Expected behavior)\n\nThe repository should've been in the \"merging\" state, in order to \nrewrite the paths using:\n\n$ git read-tree --prefix=/project/ -u foo/main\n\nIt's only a minor annoyance that can be fixed by adding an empty commit \nin advance of performing the merge, yet it took me some minutes to \nfigure out why Git does not behave as intended.\n\n## What happened instead? (Actual behavior)\n\nA merge commit was created.\n\n## What's different between what you expected and what actually happened?\n\nSaid merge commit, even though the `--no-commit` option was set.\n\n[System Info]\ngit version:\ngit version 2.44.0\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nuname: Linux 6.7.10-200.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Mar 18 \n18:56:52 UTC 2024 x86_64\ncompiler info: gnuc: 13.2\nlibc info: glibc: 2.38\n$SHELL (typically, interactive shell): /usr/bin/fish\n\n-- \nMit freundlichen Grüßen / kind regards\n\n*Jasmin Oster*\nSoftware Developer\n\nANEXIA Internetdienstleistungs GmbH\n\nE-Mail: JOster@anexia.com <mailto:DName@anexia.com>\nWeb: anexia.com <https://anexia.com/>\n\nAnschrift Hauptsitz Klagenfurt: Feldkirchner Straße 140, 9020 Klagenfurt\nGeschäftsführer: Alexander Windbichler\nFirmenbuch: FN 289918a | Gerichtsstand: Klagenfurt | UID-Nummer: AT \nU63216601\n"},{"id":"492175","messageId":"xmqqv84y73th.fsf@gitster.g","threadId":"61260","inReplyTo":"22efe19e-de44-4b6d-8e8b-57e2bddb321e@anexia.com","subject":"Re: git-merge: --no-commit is not respected on a fresh repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-04-03T17:29:14Z","receivedAt":"2024-04-03T17:29:25Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jasmin Oster <JOster@anexia.com> writes:\n\n> 1. Create a new repository: $ git init\n> 2. Add a remote: $ git remote add foo ../<path-to-another-repo>\n> 3. Fetch everything: $ git fetch --all\n> 4. Initiate a subtree merge: $ git merge -s our --no-commit foo/main\n\nThis is expected.  We are not creating any new commit, so it is\nfollowing the --no-commit option to the letter.  Obviously it is\ndifferent from what you expected to see, though ;-)\n\nThe \"merge into void\" first came to \"git pull $URL $branch\" (no\nother options) where people tried to pull into a freshly created\nrepository, where it was very clear that they wanted to have a copy\nof the upstream branch.  The \"git pull\" implementation of the\n\"pulling into void\" feature forgot that curious users may give\n\"--no-commit\", and just always fast-forwarded to the merged commit\nwithout checking if such an option was given.\n\nThe behaviour you are seeing was inherited into \"git merge\".  It\nalso always fast-forwards to the merged commit, ignoring the option.\n\nIn either case, there is no new commit created.  The history you are\nseeing is the exact history of the upstream.  If you want to\ndissociate your history from theirs and start your history anew:\n\n    $ git merge foo/main\n    $ git checkout --orphan master\n\nwould give you an unborn branch \"master\", with the merge result in\nthe working tree and in the index, without any history behind it.\nIf you wanted to, you can then rename it to main from this state\nwith:\n\n    $ git branch -M master main\n\nWe could make it more explicit with a patch like the following, but\nit probably is not worth it.  I dunno.\n\n builtin/merge.c | 2 ++\n builtin/pull.c  | 2 ++\n 2 files changed, 4 insertions(+)\n\ndiff --git c/builtin/merge.c w/builtin/merge.c\nindex 1cbd6a899c..1c3165e99a 100644\n--- c/builtin/merge.c\n+++ w/builtin/merge.c\n@@ -1434,6 +1434,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tstruct object_id *remote_head_oid;\n \t\tif (squash)\n \t\t\tdie(_(\"Squash commit into empty head not supported yet\"));\n+\t\tif (!option_commit)\n+\t\t\tdie(_(\"--no-commit into empty head not supported\"));\n \t\tif (fast_forward == FF_NO)\n \t\t\tdie(_(\"Non-fast-forward commit does not make sense into \"\n \t\t\t    \"an empty head\"));\ndiff --git c/builtin/pull.c w/builtin/pull.c\nindex 72cbb76d52..98c11ecc55 100644\n--- c/builtin/pull.c\n+++ w/builtin/pull.c\n@@ -1097,6 +1097,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \tif (is_null_oid(&orig_head)) {\n \t\tif (merge_heads.nr > 1)\n \t\t\tdie(_(\"Cannot merge multiple branches into empty head.\"));\n+\t\tif (opt_commit && !strcmp(\"--no-commit\", opt_commit))\n+\t\t\tdie(_(\"--no-commit into empty head not supported\"));\n \t\tret = pull_into_void(merge_heads.oid, &curr_head);\n \t\tgoto cleanup;\n \t}\n"}]}