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

[RFC] git --trace: trace command execution

From
MLMatthias Lederhofer <matled@gmx.net>
Date
Jun 25, 2006, 10:57 UTC
Message-ID
<E1FuSIf-0004jK-Tp@moooo.ath.cx>

Show parameters to execve/builtin-cmds before executing them. This version does not yet have a parameter --trace to git to enable this I just want to get feedback first :)

I think this is quite useful to debug what is going on since a command may be another program (shell/python/perl/.. script etc) or just an alias for a internal command. Before that many commands became built-ins this was quite easy to do with strace.

Example: % git repo-config alias.showtag trace: exec: /home/matled/local/stow/git/bin/git-repo-config alias.showtag % git showtag v1.4.1-rc1 > /dev/null trace: exec: /home/matled/local/stow/git/bin/git-showtag v1.4.1-rc1 trace: exec failed: No such file or directory trace: built-in command: git cat-file tag v1.4.1-rc1 % git showtag 'a b "c" `d` $e \f' trace: exec: /home/matled/local/stow/git/bin/git-showtag "a b \"c\" \`d\` \$e \\f" trace: exec failed: No such file or directory trace: built-in command: git cat-file tag "a b \"c\" \`d\` \$e \\f" fatal: Not a valid object name a b "c" `d` $e \f % git cat-file tag "a b \"c\" \`d\` \$e \\f" trace: built-in command: git cat-file tag "a b \"c\" \`d\` \$e \\f" fatal: Not a valid object name a b "c" `d` $e \f

print_shell_escape will escape the arguments to be used as strings in the shell to prevent ambiguity with spaces and other special characters and make them copy-and-pastable.

---
 exec_cmd.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 exec_cmd.h |    1 +
 git.c      |   10 ++++++++++
 3 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index c1539d1..85afbf3 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -87,6 +87,16 @@ int execv_git_cmd(const char **argv)
 			break;
 		}
 
+		fprintf(stderr, "trace: exec: ");
+		print_shell_escape(stderr, git_command);
+		const char **p = argv;
+		while (*(++p)) {
+			putc(' ', stderr);
+			print_shell_escape(stderr, *p);
+		}
+		putc('\n', stderr);
+		fflush(stderr);
+
 		/* argv[0] must be the git command, but the argv array
 		 * belongs to the caller, and my be reused in
 		 * subsequent loop iterations. Save argv[0] and
@@ -98,6 +108,8 @@ int execv_git_cmd(const char **argv)
 
 		/* execve() can only ever return if it fails */
 		execve(git_command, (char **)argv, environ);
+		fprintf(stderr, "trace: exec failed: %s\n", strerror(errno));
+		fflush(stderr);
 
 		argv[0] = tmp;
 	}
@@ -128,3 +140,33 @@ int execl_git_cmd(const char *cmd,...)
 	argv[argc] = NULL;
 	return execv_git_cmd(argv);
 }
+
+void print_shell_escape(FILE *stream, const char *s)
+{
+	const char *c = s;
+	short int quote = 0;
+	while (*c) {
+		if (*c == '"' || *c == '`' || *c == '$' || *c == '\\' ||
+			isspace(*c))
+		{
+			quote = 1;
+			break;
+		}
+		++c;
+	}
+
+	if (!quote) {
+		fputs(s, stream);
+		return;
+	}
+
+	putc('"', stream);
+	c = s;
+	while (*c) {
+		if (*c == '"' || *c == '`' || *c == '$' || *c == '\\')
+			putc('\\', stream);
+		putc(*c, stream);
+		++c;
+	}
+	putc('"', stream);
+}
diff --git a/exec_cmd.h b/exec_cmd.h
index 989621f..8b237fa 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -5,6 +5,7 @@ extern void git_set_exec_path(const char
 extern const char* git_exec_path(void);
 extern int execv_git_cmd(const char **argv); /* NULL terminated */
 extern int execl_git_cmd(const char *cmd, ...);
+extern void print_shell_escape(FILE *stream, const char *s);
 
 
 #endif /* __GIT_EXEC_CMD_H_ */
diff --git a/git.c b/git.c
index 94e9a4a..361fb25 100644
--- a/git.c
+++ b/git.c
@@ -198,6 +198,16 @@ static void handle_internal_command(int 
 		struct cmd_struct *p = commands+i;
 		if (strcmp(p->cmd, cmd))
 			continue;
+
+		fprintf(stderr, "trace: built-in command: git");
+		int i;
+		for (i = 0; i < argc; ++i) {
+			putc(' ', stderr);
+			print_shell_escape(stderr, argv[i]);
+		}
+		putc('\n', stderr);
+		fflush(stderr);
+
 		exit(p->fn(argc, argv, envp));
 	}
 }
-- 
1.4.GIT
Next: Junio C Hamano
Message 1 of 10 in “[RFC] git --trace: trace command execution”
  1. Matthias LederhoferJun 25, 2006
  2. Junio C HamanoJun 25, 2006
  3. Matthias LederhoferJun 25, 2006
  4. GIT_TRACE: show which built-in/external commands are executedMatthias Lederhofer, Jun 25, 2006
  5. Johannes SchindelinJun 25, 2006
  6. Petr BaudisJun 25, 2006
  7. Matthias LederhoferJun 25, 2006
  8. Johannes SchindelinJun 25, 2006
  9. Matthias LederhoferJun 28, 2006
  10. Jakub NarebskiJun 29, 2006

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.