git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] rebase: exec leaks GIT_DIR to environment

From
PWPhillip Wood <phillip.wood@talktalk.net>
Date
Oct 29, 2017, 18:34 UTC
Message-ID
<4150d979-f653-e79b-563a-1dc43f12468d@talktalk.net>
In-Reply-To
<alpine.DEB.2.21.1.1710281740070.6482@virtualbox>
On 28/10/17 17:00, Johannes Schindelin wrote:
Show 56 quoted lines
> 
> Hi Jake,
> 
> On Fri, 27 Oct 2017, Jacob Keller wrote:
> 
>> From: Jacob Keller <jacob.keller@gmail.com>
>>
>> I noticed a failure with git rebase interactive mode which causes "exec"
>> commands to be run with GIT_DIR set. When GIT_DIR is in the environment,
>> then any command which results in running a git command in
>> a subdirectory will fail because GIT_DIR=".git".
>>
>> This unfortunately breaks one of my project's Makefiles, which uses
>> git-describe to find the version information, but does so from within
>> a sub directory.
>>
>> I'm in the process of running a bisect to find where this got
>> introduced, but I suspect it's part of the rebase--helper changes that
>> happened a while ago.
> 
> A safe assumption. I do not know how the shell code managed that GIT_DIR
> reset, though:
> 
> -- snip from v2.12.0's git-rebase--interactive.sh --
>         x|"exec")
>                 read -r command rest < "$todo"
>                 mark_action_done
>                 eval_gettextln "Executing: \$rest"
>                 "${SHELL:-@SHELL_PATH@}" -c "$rest" # Actual execution
> -- snap --
> 
> Maybe you can spot it?
> 
> The fix should be as easy as
> 
> -- snip --
> diff --git a/sequencer.c b/sequencer.c
> index f2c84c2fa62..018ba8d27e2 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -1859,11 +1859,13 @@ static int error_failed_squash(struct commit *commit,
>  static int do_exec(const char *command_line)
>  {
>  	const char *child_argv[] = { NULL, NULL };
> +	const char *child_env[] = { "GIT_DIR", NULL };
>  	int dirty, status;
>  
>  	fprintf(stderr, "Executing: %s\n", command_line);
>  	child_argv[0] = command_line;
> -	status = run_command_v_opt(child_argv, RUN_USING_SHELL);
> +	status = run_command_v_opt_cd_env(child_argv, RUN_USING_SHELL, NULL,
> +					  child_env);
>  
>  	/* force re-reading of the cache */
>  	if (discard_cache() < 0 || read_cache() < 0)
> -- snap --

Just clearing GIT_DIR does not match the behavior of the shell version (tested by passing -p to avoid rebase--helper) as that passes GIT_DIR to exec commands if it has been explicitly set. I think that users that set GIT_DIR on the command line would expect it to be propagated to exec commands.

$ git rebase -px'echo $GIT_DIR' @
                                                            Merge commit
'7c2f1abd64' into phil
Executing: echo $GIT_DIR
Successfully rebased and updated refs/heads/phil.
$ env GIT_DIR=.git git rebase -px'echo $GIT_DIR' @
                                                            Merge commit
'7c2f1abd64' into phil
Executing: echo $GIT_DIR
/home/phil/Documents/src/git/.git/worktrees/git-next
Successfully rebased and updated refs/heads/phil.
Show 46 quoted lines
> *However*, your test still fails with this, as
> 
> - your added test tries to remove the directory with -ff instead of -rf
> 
> - it tries to run `git rebase --abort` afterwards, which fails with my fix
>   because there is no rebase in progress
> 
> - instead of `cd subdir && ...`, it calls `>cd subdir && ...`, which
>   causes it to abort with a "subdir: not fonud"
> 
> So I need this, too, to make it all work:
> 
> -- snip --
> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> index 60ab5136f70..967caab222a 100755
> --- a/t/t3404-rebase-interactive.sh
> +++ b/t/t3404-rebase-interactive.sh
> @@ -108,13 +108,13 @@ test_expect_success 'rebase -i with the exec command runs from tree root' '
>  	rm -fr subdir
>  '
>  
> -test_expect_failure 'rebase -i with the exec git commands in subdirs still work' '
> -	test_when_finished "rm -ff subdir" &&
> -	test_when_finished "git rebase --abort" &&
> +test_expect_success 'rebase -i with the exec git commands in subdirs still work' '
> +	test_when_finished "rm -rf subdir" &&
> +	test_when_finished "git rebase --abort || :" &&
>  	git checkout master &&
>  	mkdir subdir && (cd subdir &&
>  	set_fake_editor &&
> -	FAKE_LINES="1 exec_>cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \
> +	FAKE_LINES="1 exec_cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \
>  		git rebase -i HEAD^
>  	)
>  '
> -- snap --
> 
> I only had time to write these two patches, and to verify that t3404
> passes now, but not that anything else passes, neither to write a proper
> commit message.
> 
> Maybe you can take it from there?
> 
> Ciao,
> Dscho
> 
Previous: Jacob KellerNext: Junio C Hamano
Message 4 of 12 in “rebase: exec leaks GIT_DIR to environment”
  1. rebase: exec leaks GIT_DIR to environmentJacob Keller, Oct 28, 2017
  2. Johannes SchindelinOct 28, 2017
  3. Jacob KellerOct 28, 2017
  4. Phillip WoodOct 29, 2017
  5. Junio C HamanoOct 30, 2017
  6. Jacob KellerOct 30, 2017
  7. Junio C HamanoOct 30, 2017
  8. Jacob KellerOct 30, 2017
  9. Phillip WoodOct 30, 2017
  10. Johannes SchindelinOct 30, 2017
  11. Jacob KellerOct 31, 2017
  12. Jacob KellerOct 30, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.