{"thread":{"id":"59574","subject":"Re: 'git config --edit' unexpected behavior","startedAt":"2023-04-10T23:23:25Z","lastAt":"2023-04-11T09:42:06Z","messageCount":2,"participants":["Mervin Guy","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"475100","messageId":"C65981B6-49FA-4A62-84D6-541D3CFF0541@mervin.works","threadId":"59574","inReplyTo":"D6798678-9CC3-416F-B238-F3D28EC910B2@mervin.works","subject":"Re: 'git config --edit' unexpected behavior","fromName":"Mervin Guy","fromEmail":"mail@mervin.works","sentAt":"2023-04-10T23:05:12Z","receivedAt":"2023-04-10T23:23:25Z","isPatch":false,"sender":{"key":"mail@mervin.works","avatar":null},"body":"I'm confident there is an error in the `git config --global -e` pipeline though (very likely git.c), because when using git-aliases the function performs as expected.\n\nMy current alias `ec` pointing to the command `!vi $HOME/.gitconfig` - where $HOME is `/root`. The full command looks like `git ec` and works as expected.\n\nMeaning that the only difference between the failed-run and successful-run was calling the git built-in `git config --global -e`.\n\n> On Apr 10, 2023, at 16:49, Hello World! <mail@mervin.works> wrote:\n> \n> ﻿Using the command, the trace says it’s using 'vi /root/.gitconfig' - which is indeed the set editor.\n> \n> For more verbosity, the call-chain is 'git.c' (trace: built-in: git config) → 'run_command.c' (trace: run_command: 'vi /root/.gitconfig') which doesn’t seem strange.\n>>> On Apr 10, 2023, at 16:25, Jeff King <peff@peff.net> wrote:\n>>> ﻿ On Mon, Apr 10, 2023 at 03:44:26PM -0400, Mervin Guy wrote:\n>>> \n>>> What did you do before the bug happened? (Steps to reproduce your issue)\n>>> - Changed my directory to a git-repo I was working on, using 'cd <directory_name>'. Then I ran 'git config --global -e'.\n>>> What did you expect to happen? (Expected behavior)\n>>> - I exepected the command to display my current-config file, with all settings included, in my editor.\n>>> What happened instead? (Actual behavior)\n>>> - My config-file was overwritten and displayed a default-setup message, the config-file was lost after this point.\n>>> I experimented with different ways of activating the command, but they all led to an overwrite of the file.\n>> \n>> That's certainly unexpected. \"git config --global -e\" works fine for me.\n>> And Git itself won't overwrite the file; it will run your editor with\n>> the name of the file, and the editor is responsible for any writing.\n>> Which editor are you trying to use? Can you try running with:\n>> \n>> GIT_TRACE=1 git config --global -e\n>> \n>> which should show the editor command that Git runs.\n>> \n>> -Peff\n"},{"id":"475135","messageId":"20230411094156.GC398350@coredump.intra.peff.net","threadId":"59574","inReplyTo":"C65981B6-49FA-4A62-84D6-541D3CFF0541@mervin.works","subject":"Re: 'git config --edit' unexpected behavior","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2023-04-11T09:41:56Z","receivedAt":"2023-04-11T09:42:06Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Apr 10, 2023 at 07:05:12PM -0400, Mervin Guy wrote:\n\n> I'm confident there is an error in the `git config --global -e`\n> pipeline though (very likely git.c), because when using git-aliases\n> the function performs as expected.\n> \n> My current alias `ec` pointing to the command `!vi $HOME/.gitconfig` -\n> where $HOME is `/root`. The full command looks like `git ec` and works\n> as expected.\n> \n> Meaning that the only difference between the failed-run and\n> successful-run was calling the git built-in `git config --global -e`.\n\nOK, so we can guess it has to do with the \"--edit\" option specifically,\nand your editor is doing what we'd expect. The main thing that code is\ndoing is just opening the editor, but there's this curious bit of code\nbefore it does so:\n\n  $ sed -ne '851,+11p' builtin/config.c\n  \t\tif (use_global_config) {\n  \t\t\tint fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);\n  \t\t\tif (fd >= 0) {\n  \t\t\t\tchar *content = default_user_config();\n  \t\t\t\twrite_str_in_full(fd, content);\n  \t\t\t\tfree(content);\n  \t\t\t\tclose(fd);\n  \t\t\t}\n  \t\t\telse if (errno != EEXIST)\n  \t\t\t\tdie_errno(_(\"cannot create configuration file %s\"), config_file);\n  \t\t}\n  \t\tlaunch_editor(config_file, NULL, NULL);\n\nThat shouldn't be overwriting your existing file, since O_EXCL will\nrefuse to open the file in that case.\n\nBut I wonder if something funny is going on with the file selection. We\nsupport both the traditional $HOME/.gitconfig location, but also the xdg\nlocation (usually $HOME/.config/git/config, but $XDG_CONFIG_HOME can\ntweak that).\n\nWhen reading config for most commands, we will generally pull from both\nsources. But for \"git config --global\", we have to pick one to operate\non, both for reading and writing. The logic is supposed to prefer\n$HOME/.gitconfig, but use the xdg location if it exists and the $HOME\none doesn't.\n\nFrom your output:\n\n> > Using the command, the trace says it’s using 'vi /root/.gitconfig' -\n> > which is indeed the set editor.\n\nit's picking the $HOME one. You said you had previous contents that were\noverwritten. How did you add them originally, and might they have been\nin the xdg location? Can you see if there is anything in /root/.config/git?\n\nI admit I still don't know how we'd trigger this case; if the file did\nexist then we should never use /root/.config in the first place.\n\nAnother left-field possibility: is /root on an unusual filesystem (e.g.,\na networked one) where O_EXCL might not behave as it should?\n\n-Peff\n"}]}