Skip to contentSkip to conversation

Teach git to change to a given directory using -C option

PATCH In review Nazri Ramliy 2 participants 2 messages Jun 15, 2016 Documentation

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 Teach git to change to a given directory using -C option

Hi,

Sorry it took me a while to get back on this. Reroll at the bottom ...

Quoted 9 lines · Junio C Hamano
Quoted 3 lines · Nazri Ramliy

Subject: git: run in a directory given with -C option

This is similar in spirit to to "make -C dir ..." and "tar -C dir ...".

The doubled-"to to" which I locally fixed when I queued the last one (together with other rewording to make it more agreeable and easier to read) somehow came back ;-) Will fix locally again.

I must have mistakenly made the revision on top of my local changes instead of the one in next - I didn't notice the fix. Thanks for the fix.

Quoted 12 lines

Review

Quoted 3 lines

+-C <path>::

(quoted diff) +2 -0
+     Run as if git was started in '<path>' instead of the current working
+     directory.  When multiple '-C' options are given, each subsequent

I think this should be -C to typeset it as "typed literally".

Review

Quoted 5 lines
(quoted diff) +5 -0
+     non-absolute `-C <path>` is interpreted relative to the preceding `-C
+     <path>`.
++
+This option affects options that expect path name like '--git-dir' and
+'--work-tree' in that their interpretations of the path names would be
Quoted 5 lines

Likewise for --git-dir and --work-tree.

Quoted 1 line

+made relative to the working directory caused by the '-C' option. For

and here.

Now I'm noticing that you've already made the above fixes in next ;)

Quoted 10 lines
Quoted 10 lines
t/t0056-git-C.sh new file +4 -0
new file mode 100755
index 0000000..c0006da
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+test_description='"-C <path>" option and its effects on other path-related options'
+
Quoted 8 lines

t/t0056-git-C.sh line 10

Quoted 6 lines
t/t0056-git-C.sh new file +6 -0
+. ./test-lib.sh
+
+test_expect_success '"git -C <path>" runs git from the directory <path>' '
+     test_create_repo dir1 &&
+     echo 1 >dir1/a.txt &&
+     (cd dir1 && git add a.txt && git commit -m "initial in dir1") &&

Curious why this does not use -C here.

It didn't use -C there because it's in the "prepare the expected test output" stage and we want that to succeed, whether -C works or not - we haven't reached the part where we are actually testing the -C option, which is right after that:

Quoted 15 lines

t/t0056-git-C.sh line 19

Quoted 9 lines
t/t0056-git-C.sh new file +9 -0
+     echo "initial in dir1" >expected &&
+     git -C dir1 log --format=%s >actual &&
+     test_cmp expected actual
+'
+
+test_expect_success 'Multiple -C options: "-C dir1 -C dir2" is equivalent to "-C dir1/dir2"' '
+     test_create_repo dir1/dir2 &&
+     echo 1 >dir1/dir2/a.txt &&
+     git -C dir1/dir2 add a.txt &&

Because "a.txt" exists in both dir1 and dir1/dir2, this has less chance of catching a bug (if somebody breaks the feature to run it in dir1 not dir1/dir2, "add" will happily say "Oh, I found something to add", instead of saying "Huh? there is no such path".

Quoted 8 lines

If you used b.txt instead, you would catch such a breakage.

Remember, tests are not about demonstrating how cool the new feature is and/or how well it works in an expected setting. Imagine ways other people can break your spiffy new feature in later patches, and design tests that are more likely to catch them.

The same comment applies throughout the remainder of this script.

Noted, but I my imagination is limited at the moment so I haven't come up with new tests to that effect yet ;)

Quoted 7 lines

t/t0056-git-C.sh line 21

Quoted 2 lines
t/t0056-git-C.sh new file +2 -0
+     echo "initial in dir1/dir2" >expected &&
+     git -C dir1/dir2 commit -m "initial in dir1/dir2" &&

to reduce possibilities of breaking this test in the future due to typos (e.g. somebody may want to say "initial commit in dir1/dir2"), doing this may be a better idea:

Quoted 5 lines
        msg="initial in dir1/dir2" &&
        echo "$msg" >expected &&
        git -C dir1/dir2 commit -m "$msg" &&

The same comment applies to the previous one.

Fixed.

nazri
-- >8 --
Subject: git: run in a directory given with -C option

This is similar in spirit to "make -C dir ..." and "tar -C dir ...".

It takes more keypresses to invoke git command in a different directory without leaving the current directory:

1. (cd ~/foo && git status)
git --git-dir=~/foo/.git --work-dir=~/foo status GIT_DIR=~/foo/.git GIT_WORK_TREE=~/foo git status
2. (cd ../..; git grep foo)
3. for d in d1 d2 d3; do (cd $d && git svn rebase); done

The methods shown above are acceptable for scripting but are too cumbersome for quick command line invocations.

With this new option, the above can be done with fewer keystrokes:

1. git -C ~/foo status
2. git -C ../.. grep foo
3. for d in d1 d2 d3; do git -C $d svn rebase; done

A new test script is added to verify the behavior of this option with other path-related options like --git-dir and --work-tree.

---
 Documentation/git.txt | 16 +++++++++-
 git.c                 | 13 +++++++-
 t/t0056-git-C.sh      | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100755 t/t0056-git-C.sh
Documentation/git.txt +15 -1
index c4f0ed5..5d68d33 100644
@@ -9,7 +9,7 @@ git - the stupid content tracker
 SYNOPSIS
 --------
 [verse]
-'git' [--version] [--help] [-c <name>=<value>]
+'git' [--version] [--help] [-C <path>] [-c <name>=<value>]
     [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
     [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
     [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
@@ -395,6 +395,20 @@ displayed. See linkgit:git-help[1] for more information,
 because `git --help ...` is converted internally into `git
 help ...`.
 
+-C <path>::
+	Run as if git was started in '<path>' instead of the current working
+	directory.  When multiple `-C` options are given, each subsequent
+	non-absolute `-C <path>` is interpreted relative to the preceding `-C
+	<path>`.
++
+This option affects options that expect path name like `--git-dir` and
+`--work-tree` in that their interpretations of the path names would be
+made relative to the working directory caused by the `-C` option. For
+example the following invocations are equivalent:
+
+    git --git-dir=a.git --work-tree=b -C c status
+    git --git-dir=c/a.git --work-tree=c/b status
+
 -c <name>=<value>::
 	Pass a configuration parameter to the command. The value
 	given will override values from configuration files.
git.c +12 -1
index b3893e7..1188979 100644
@@ -7,7 +7,7 @@
 #include "commit.h"
 
 const char git_usage_string[] =
-	"git [--version] [--help] [-c name=value]\n"
+	"git [--version] [--help] [-C <path>] [-c name=value]\n"
 	"           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
 	"           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]\n"
 	"           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
@@ -165,6 +165,17 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 			set_alternate_shallow_file((*argv)[0]);
 			if (envchanged)
 				*envchanged = 1;
+		} else if (!strcmp(cmd, "-C")) {
+			if (*argc < 2) {
+				fprintf(stderr, "No directory given for -C.\n" );
+				usage(git_usage_string);
+			}
+			if (chdir((*argv)[1]))
+				die_errno("Cannot change to '%s'", (*argv)[1]);
+			if (envchanged)
+				*envchanged = 1;
+			(*argv)++;
+			(*argc)--;
 		} else {
 			fprintf(stderr, "Unknown option: %s\n", cmd);
 			usage(git_usage_string);
t/t0056-git-C.sh new file +84 -0

84 lines not on this page · raw message

Signature · 1 line
1.8.4.411.g6835a8c
#1 lore raw
Quoted 1 line · Nazri Ramliy

Now I'm noticing that you've already made the above fixes in next ;)

Yes. I said I'd locally tweak and queue, didn't I?

Quoted 10 lines
Quoted 6 lines

t/t0056-git-C.sh

Quoted 4 lines
t/t0056-git-C.sh new file +4 -0
+test_expect_success '"git -C <path>" runs git from the directory <path>' '
+     test_create_repo dir1 &&
+     echo 1 >dir1/a.txt &&
+     (cd dir1 && git add a.txt && git commit -m "initial in dir1") &&

Curious why this does not use -C here.

It didn't use -C there because it's in the "prepare the expected test output" stage and we want that to succeed, whether -C works or not - we haven't reached the part where we are actually testing the -C option,

Good thinking.

Will queue as an incremental update on top of what is already in 'next'.

Thanks.