git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* git-checkout-index, flag ordering and --prefix kludgy handling
@ 2005-10-16 19:14 Blaisorblade
  2005-10-17 22:58 ` Junio C Hamano
  2005-10-17 22:58 ` Linus Torvalds
  0 siblings, 2 replies; 10+ messages in thread
From: Blaisorblade @ 2005-10-16 19:14 UTC (permalink / raw)
  To: git

I already knew that git-checkout-cache -a -f is wrong. But I didn't know that 

git-checkout-index -a --prefix=/home/paolo/Uml/space.mnt/paolo/Linux-2.6.git/

is. It checks out the files in the cwd, then parses --prefix and does nothing 
there, as no name is specified.

Also, the SYNOPSIS of the man page is rather misleading:

git-checkout-index [-u] [-q] [-a] [-f] [-n] [--prefix=<string>] [--] <file>...

seems to suggest that prefix can go after -f, how it's reasonable to do.

At least, this should be documented in the man page; but I think that fixing 
this (via two getopt() invocations rather than one, the first for flags like 
--prefix and the rest for actions) is probably a better thing to do.

Actually, given the audience, saying that "-a" and "filename" are both actions 
(which are executed when seen on the command line) would be a better 
explaination - and a reference to the "find" command (which behaves 
similarly) would be worth.

However, find *does* accept "options" (like -maxdepth) in any cmd line place.
-- 
Inform me of my mistakes, so I can keep imitating Homer Simpson's "Doh!".
Paolo Giarrusso, aka Blaisorblade (Skype ID "PaoloGiarrusso", ICQ 215621894)
http://www.user-mode-linux.org/~blaisorblade


		
___________________________________ 
Yahoo! Messenger: chiamate gratuite in tutto il mondo 
http://it.messenger.yahoo.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: git-checkout-index, flag ordering and --prefix kludgy handling
  2005-10-16 19:14 git-checkout-index, flag ordering and --prefix kludgy handling Blaisorblade
@ 2005-10-17 22:58 ` Junio C Hamano
  2005-10-17 22:58 ` Linus Torvalds
  1 sibling, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2005-10-17 22:58 UTC (permalink / raw)
  To: Blaisorblade; +Cc: git

Blaisorblade <blaisorblade@yahoo.it> writes:

> I already knew that git-checkout-cache -a -f is wrong. But I
> didn't know that
>
> git-checkout-index -a --prefix=/home/paolo/Uml/space.mnt/paolo/Linux-2.6.git/
>
> is.

> At least, this should be documented in the man page;...


How about a bit further clarification on top of what is there,
like this?

 ------------
[PATCH] clarify that '-a' is really special in checkout-index.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt
index 1ba6fb2..838059f 100644
--- a/Documentation/git-checkout-index.txt
+++ b/Documentation/git-checkout-index.txt
@@ -44,13 +44,15 @@ OPTIONS
 --::
 	Do not interpret any more arguments as options.
 
-Note that the order of the flags matters:
+Note that the order of the flags matters for `-a` flag:
 
      git-checkout-index -a -f file.c
 
 will first check out all files listed in the cache (but not overwrite
 any old ones), and then force-checkout `file.c` a second time (ie that
 one *will* overwrite any old contents with the same filename).
+In other words, `-a` means "operate as if names of all files were
+given here, with the flags given up to this point."
 
 Also, just doing "git-checkout-index" does nothing. You probably meant
 "git-checkout-index -a". And if you want to force it, you want

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: git-checkout-index, flag ordering and --prefix kludgy handling
  2005-10-16 19:14 git-checkout-index, flag ordering and --prefix kludgy handling Blaisorblade
  2005-10-17 22:58 ` Junio C Hamano
@ 2005-10-17 22:58 ` Linus Torvalds
  2005-10-18  0:33   ` Junio C Hamano
  1 sibling, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2005-10-17 22:58 UTC (permalink / raw)
  To: Blaisorblade; +Cc: git



On Sun, 16 Oct 2005, Blaisorblade wrote:
>
> I already knew that git-checkout-cache -a -f is wrong. But I didn't know that 
> 
> git-checkout-index -a --prefix=/home/paolo/Uml/space.mnt/paolo/Linux-2.6.git/
> 
> is. It checks out the files in the cwd, then parses --prefix and does nothing 
> there, as no name is specified.

Yeah, somebody should really fix the command line parsing. 

I think it's only git-checkout-index that _really_ needs fixing, since it 
has such a fragile thing right now.

Here's a totally untested patch. Do you want to test it?

It also makes it illegal to mix "-a" and explicit filenames, since the 
semantics of that has now changed (before, the order of the filename and 
the "-a" mattered. Now it no longer does. Better disallow it, than let 
people maybe think they get something else that they do).

Danger, Will Robinson! Untested!

		Linus

---
diff --git a/checkout-index.c b/checkout-index.c
index 9784532..dab3778 100644
--- a/checkout-index.c
+++ b/checkout-index.c
@@ -87,8 +87,9 @@ static struct cache_file cache_file;
 
 int main(int argc, char **argv)
 {
-	int i, force_filename = 0;
+	int i;
 	int newfd = -1;
+	int all = 0;
 
 	if (read_cache() < 0) {
 		die("invalid cache");
@@ -96,58 +97,70 @@ int main(int argc, char **argv)
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
-		if (!force_filename) {
-			if (!strcmp(arg, "-a")) {
-				checkout_all();
-				continue;
-			}
-			if (!strcmp(arg, "--")) {
-				force_filename = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-f")) {
-				state.force = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-q")) {
-				state.quiet = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-n")) {
-				state.not_new = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-u")) {
-				state.refresh_cache = 1;
-				if (newfd < 0)
-					newfd = hold_index_file_for_update
-						(&cache_file,
-						 get_index_file());
-				if (newfd < 0)
-					die("cannot open index.lock file.");
-				continue;
-			}
-			if (!memcmp(arg, "--prefix=", 9)) {
-				state.base_dir = arg+9;
-				state.base_dir_len = strlen(state.base_dir);
-				continue;
-			}
-			if (arg[0] == '-')
-				usage(checkout_cache_usage);
-		}
-		if (state.base_dir_len) {
-			/* when --prefix is specified we do not
-			 * want to update cache.
-			 */
-			if (state.refresh_cache) {
-				close(newfd); newfd = -1;
-				rollback_index_file(&cache_file);
-			}
-			state.refresh_cache = 0;
+
+		if (!strcmp(arg, "--")) {
+			i++;
+			break;
+		}
+		if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) {
+			all = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-f") || !strcmp(arg, "--force")) {
+			state.force = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
+			state.quiet = 1;
+			continue;
 		}
+		if (!strcmp(arg, "-n") || !strcmp(arg, "--no-create")) {
+			state.not_new = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-u") || !strcmp(arg, "--index")) {
+			state.refresh_cache = 1;
+			if (newfd < 0)
+				newfd = hold_index_file_for_update
+					(&cache_file,
+					 get_index_file());
+			if (newfd < 0)
+				die("cannot open index.lock file.");
+			continue;
+		}
+		if (!memcmp(arg, "--prefix=", 9)) {
+			state.base_dir = arg+9;
+			state.base_dir_len = strlen(state.base_dir);
+			continue;
+		}
+		if (arg[0] == '-')
+			usage(checkout_cache_usage);
+		break;
+	}
+
+	if (state.base_dir_len) {
+		/* when --prefix is specified we do not
+		 * want to update cache.
+		 */
+		if (state.refresh_cache) {
+			close(newfd); newfd = -1;
+			rollback_index_file(&cache_file);
+		}
+		state.refresh_cache = 0;
+	}
+
+	/* Check out named files first */
+	for ( ; i < argc; i++) {
+		const char *arg = argv[i];
+
+		if (all)
+			die("git-checkout-index: don't mix '--all' and explicit filenames");
 		checkout_file(arg);
 	}
 
+	if (all)
+		checkout_all();
+
 	if (0 <= newfd &&
 	    (write_cache(newfd, active_cache, active_nr) ||
 	     commit_index_file(&cache_file)))

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: git-checkout-index, flag ordering and --prefix kludgy handling
  2005-10-17 22:58 ` Linus Torvalds
@ 2005-10-18  0:33   ` Junio C Hamano
  2005-10-18  1:28     ` Linus Torvalds
  0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2005-10-18  0:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Linus Torvalds <torvalds@osdl.org> writes:

> Yeah, somebody should really fix the command line parsing. 
>
> I think it's only git-checkout-index that _really_ needs fixing, since it 
> has such a fragile thing right now.

Good to hear that you finally said it.

The patch looks good.  Thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: git-checkout-index, flag ordering and --prefix kludgy handling
  2005-10-18  0:33   ` Junio C Hamano
@ 2005-10-18  1:28     ` Linus Torvalds
  2005-10-18  2:27       ` Junio C Hamano
  0 siblings, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2005-10-18  1:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git



On Mon, 17 Oct 2005, Junio C Hamano wrote:
>
> The patch looks good.  Thanks.

Btw, I'd really like a "git checkout" that can do the per-file thing, 
instead of always using the equivalent of git-checkout-index with "-a".

It's actually one of the few places where I still use the raw git 
commands, doing things like

	git-checkout-index -u -f filename

and I suspect that a lot of people would prefer that

	git checkout filename

would just do that. Instead, we error out ("no such branch"). Which 
isn't even what I want, and almost certainly not what most CVS users want 
(they're used to checking out individual files).

Of course, in the generic case, that would require git-read-tree to take a 
list of filenames (which would act as a "mask" for any activity against 
the old index if one was loaded), but that's a pretty big thing. Even if 
it's admittedly also potentially very useful too..

But even just a total special case (giving a filename would force the 
checkout, no read-tree, no nothing, just force the old index contents) 
might be acceptable and would only require some script hackery.

		Linus

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: git-checkout-index, flag ordering and --prefix kludgy handling
  2005-10-18  1:28     ` Linus Torvalds
@ 2005-10-18  2:27       ` Junio C Hamano
  2005-10-18  2:48         ` Linus Torvalds
  2005-10-18  8:34         ` [PATCH] git-checkout: revert specific paths to either index or a given tree-ish Junio C Hamano
  0 siblings, 2 replies; 10+ messages in thread
From: Junio C Hamano @ 2005-10-18  2:27 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Linus Torvalds <torvalds@osdl.org> writes:

> Btw, I'd really like a "git checkout" that can do the per-file thing, 
> instead of always using the equivalent of git-checkout-index with "-a".
>
> It's actually one of the few places where I still use the raw git 
> commands, doing things like
>
> 	git-checkout-index -u -f filename
>
> and I suspect that a lot of people would prefer that
>
> 	git checkout filename
>
> would just do that. Instead, we error out ("no such branch"). Which 
> isn't even what I want, and almost certainly not what most CVS users want 
> (they're used to checking out individual files).

Yes, it has been on the TODO list for quite some time.

One reason I have not done nor said much about this was because
I've been thinking about making the branch/refname more explicit
on our command line.

Currently, we tell 'git-rev-parse' to tell refnames and other
non-flag parameters apart, which in practice does not result in
much confusion, but I think it is not quite right.

I used to have a local branch, only to fetch updates from
paulus, and naturally the branch was called 'gitk'.  But we have
a file called gitk sitting at the top level of the tree, and
'git diff gitk gitk' was not really working as well as I would
have liked ('git diff heads/gitk gitk' should have worked, but I
do not think it did).  Since then this forced me to rename the
branch to 'paulus' X-<.

On the other hand, if there is no ambiguity, I do not think
forcing people to always spell out '-r' like CVS or SVN do
is not necessary:

        $ git diff -r master^^ -r master ;# two commits
        $ git diff -r v0.99.8		 ;# changes since that tag
	$ git checkout -r master
        $ git checkout -r master $filename

This checkout optionally taking filename is introducing one more
ambiguity, and I was reluctant to do so before deciding what to
do about other commands.

Another thing I was thinking was that this might be better
implemented as a separate command that can revert the working
tree file to an artibtrary tree-ish as well.  So:

	$ git xxxxxx --index file1 file2...

would do your 'git-checkout-index -f -u file1 file2...', while

	$ git xxxxxx file1 file2...

would do an equivalent of:

	git ls-tree HEAD file1 file2... |
        sed -e 's/^\([0-7]*\) [^ ]* /\1 /' |
        git-update-index --index-info
        git-checkout-index -f -u file1 file2...

or even:

	$ git xxxxxx HEAD^^ file1 file2...

would give you back file1 and file2 from two revs back.  Of
course, to avoid ambiguities, the last one will be spelled as 

	$ git xxxxxx -r HEAD^^ file1 file2...

if people find that a separate command is cleaner.

Anyway, in the meantime...

 ------------
[PATCH] checking out individual files from index.

'git checkout filename1 filename2...' can be used to revert the
changes you made to files in the working tree to the version
recorded in the index file.

Signed-off-by: Signed-off-by: Junio C Hamano <junkio@cox.net>

---

diff --git a/git-checkout.sh b/git-checkout.sh
index 2c053a3..6af71a2 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -6,6 +6,7 @@ new=
 force=
 branch=
 newbranch=
+
 while [ "$#" != "0" ]; do
     arg="$1"
     shift
@@ -24,19 +25,28 @@ while [ "$#" != "0" ]; do
 		force=1
 		;;
 	*)
-		rev=$(git-rev-parse --verify "$arg^0" 2>/dev/null) ||
-			die "I don't know any '$arg'."
-		if [ -z "$rev" ]; then
-			echo "unknown flag $arg"
-			exit 1
-		fi
-		if [ "$new" ]; then
-			echo "Multiple revisions?"
-			exit 1
-		fi
-		new="$rev"
-		if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
-			branch="$arg"
+		if rev=$(git-rev-parse --verify "$arg^0" 2>/dev/null)
+		then
+			if [ -z "$rev" ]; then
+				echo "unknown flag $arg"
+				exit 1
+			fi
+			if [ "$new" ]; then
+				echo "Multiple revisions?"
+				exit 1
+			fi
+			new="$rev"
+			if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
+				branch="$arg"
+			fi
+		else
+			# check out individual files from index
+			if test "$new" || test "$newbranch"
+			then
+				die "checkout and switch tree?"
+			fi
+			git-checkout-index -f -u "$arg" "$@"
+			exit $?
 		fi
 		;;
     esac

Compilation finished at Mon Oct 17 19:08:29

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: git-checkout-index, flag ordering and --prefix kludgy handling
  2005-10-18  2:27       ` Junio C Hamano
@ 2005-10-18  2:48         ` Linus Torvalds
  2005-10-18  5:49           ` Teach "git diff" to handle filenames startign with '-' Linus Torvalds
  2005-10-18  8:34         ` [PATCH] git-checkout: revert specific paths to either index or a given tree-ish Junio C Hamano
  1 sibling, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2005-10-18  2:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git



On Mon, 17 Oct 2005, Junio C Hamano wrote:
> 
> One reason I have not done nor said much about this was because
> I've been thinking about making the branch/refname more explicit
> on our command line.

Yes, I know it's ambigious at times, but it really is very convenient. 
Usually we allow a "--" to say where a filename starts when it _is_ 
ambiguous.

However, you're right, we fail that at times. In particular, git-rev-parse 
fails it.

Something like this?

		Linus
---
diff --git a/rev-parse.c b/rev-parse.c
index 41b9dae..85230df 100644
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -151,6 +151,12 @@ static void show_datestring(const char *
 	show(buffer);
 }
 
+static void show_file(const char *arg)
+{
+	if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV))
+		show(arg);
+}
+
 int main(int argc, char **argv)
 {
 	int i, as_is = 0, verify = 0;
@@ -162,7 +168,7 @@ int main(int argc, char **argv)
 		char *dotdot;
 	
 		if (as_is) {
-			show(arg);
+			show_file(arg);
 			continue;
 		}
 		if (*arg == '-') {
@@ -282,9 +288,7 @@ int main(int argc, char **argv)
 		}
 		if (verify)
 			die("Needed a single revision");
-		if ((filter & (DO_NONFLAGS|DO_NOREV)) ==
-		    (DO_NONFLAGS|DO_NOREV))
-			show(arg);
+		show_file(arg);
 	}
 	show_default();
 	if (verify && revs_count != 1)

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Teach "git diff" to handle filenames startign with '-'
  2005-10-18  2:48         ` Linus Torvalds
@ 2005-10-18  5:49           ` Linus Torvalds
  2005-10-18  5:57             ` Handle "-" at beginning of filenames, part 3 Linus Torvalds
  0 siblings, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2005-10-18  5:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git


It adds "--" to the git-diff.sh scripts, to keep any filenames that start 
with a "-" from being confused with an option.

But in order to do that, it needs to teach git-diff-files to honor "--".

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---

On Mon, 17 Oct 2005, Linus Torvalds wrote:
> 
> Yes, I know it's ambigious at times, but it really is very convenient. 
> Usually we allow a "--" to say where a filename starts when it _is_ 
> ambiguous.

This is on top of the rev-parse.c diff (it's strictly independent, but it 
needs the rev-parse.c one to make any sense, since without the rev-parse.c 
fix for -- handling, "git diff" won't work regardless).

diff --git a/diff-files.c b/diff-files.c
index 8a8f9b6..1789939 100644
--- a/diff-files.c
+++ b/diff-files.c
@@ -41,6 +41,11 @@ int main(int argc, const char **argv)
 	git_config(git_default_config);
 	diff_setup(&diff_options);
 	while (1 < argc && argv[1][0] == '-') {
+		if (!strcmp(argv[1], "--")) {
+			argv++;
+			argc--;
+			break;
+		}
 		if (!strcmp(argv[1], "-q"))
 			silent = 1;
 		else if (!strcmp(argv[1], "-r"))
diff --git a/git-diff.sh b/git-diff.sh
index 84a152a..b3ec84b 100755
--- a/git-diff.sh
+++ b/git-diff.sh
@@ -28,16 +28,16 @@ case "$rev" in
 ?*' '^?*)
 	begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
 	end=$(expr "$rev" : '.\([0-9a-f]*\). .*') || exit
-	cmd="git-diff-tree $flags $begin $end $files"
+	cmd="git-diff-tree $flags $begin $end -- $files"
 	;;
 ?*' '?*)
-	cmd="git-diff-tree $flags $rev $files"
+	cmd="git-diff-tree $flags $rev -- $files"
 	;;
 ?*' ')
-	cmd="git-diff-index $flags $rev $files"
+	cmd="git-diff-index $flags $rev -- $files"
 	;;
 '')
-	cmd="git-diff-files $flags $files"
+	cmd="git-diff-files $flags -- $files"
 	;;
 *)
 	die "I don't understand $*"

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Handle "-" at beginning of filenames, part 3
  2005-10-18  5:49           ` Teach "git diff" to handle filenames startign with '-' Linus Torvalds
@ 2005-10-18  5:57             ` Linus Torvalds
  0 siblings, 0 replies; 10+ messages in thread
From: Linus Torvalds @ 2005-10-18  5:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git


This fixes the default built-in exec() of "diff" to add a "--" before the 
filenames, so that if a filename starts with a "-", the diff program won't 
think it's an option.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---

This should complete the series. Now all the parts should be safe and pass 
on "--" properly. Knock wood.


On Mon, 17 Oct 2005, Linus Torvalds wrote:
> 
> It adds "--" to the git-diff.sh scripts, to keep any filenames that start 
> with a "-" from being confused with an option.

diff --git a/diff.c b/diff.c
index cbb8632..d6b5086 100644
--- a/diff.c
+++ b/diff.c
@@ -134,7 +134,7 @@ static void builtin_diff(const char *nam
 {
 	int i, next_at, cmd_size;
 	const char *const diff_cmd = "diff -L%s%s -L%s%s";
-	const char *const diff_arg  = "%s %s||:"; /* "||:" is to return 0 */
+	const char *const diff_arg  = "-- %s %s||:"; /* "||:" is to return 0 */
 	const char *input_name_sq[2];
 	const char *path0[2];
 	const char *path1[2];

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH] git-checkout: revert specific paths to either index or a given tree-ish.
  2005-10-18  2:27       ` Junio C Hamano
  2005-10-18  2:48         ` Linus Torvalds
@ 2005-10-18  8:34         ` Junio C Hamano
  1 sibling, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2005-10-18  8:34 UTC (permalink / raw)
  To: git; +Cc: Linus Torvalds

When extra paths arguments are given, git-checkout reverts only those
paths to either the version recorded in the index or the version
recorded in the given tree-ish.

This has been on the TODO list for quite a while.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

    Junio C Hamano <junkio@cox.net> writes:

    > Linus Torvalds <torvalds@osdl.org> writes:
    >
    >> Btw, I'd really like a "git checkout" that can do the per-file thing, 
    >> instead of always using the equivalent of git-checkout-index with "-a".
    >>
    >> and I suspect that a lot of people would prefer that
    >>
    >> 	git checkout filename
    >>
    >> would just do that. Instead, we error out ("no such branch"). Which 
    >> isn't even what I want, and almost certainly not what most CVS users want 
    >> (they're used to checking out individual files).

    I've redone this a bit differently since last night's "in
    the meantime..." patch, so that we can pull selected paths
    out of arbitrary tree-ish.

 git-checkout.sh                |   79 ++++++++++++++++++++++++++++++++--------
 Documentation/git-checkout.txt |   42 ++++++++++++++++++++-
 2 files changed, 103 insertions(+), 18 deletions(-)

applies-to: f7e1a8387657c4da9991861ae44347813b67bc46
4aaa702794447d9b281dd22fe532fd61e02434e1
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index f753c14..b7bb1b4 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -7,12 +7,24 @@ git-checkout - Checkout and switch to a 
 
 SYNOPSIS
 --------
-'git-checkout' [-f] [-b <new_branch>] [<branch>]
+'git-checkout' [-f] [-b <new_branch>] [<branch>] [<paths>...]
 
 DESCRIPTION
 -----------
-Updates the index and working tree to reflect the specified branch,
-<branch>. Updates HEAD to be <branch> or, if specified, <new_branch>.
+
+When <paths> are not given, this command switches branches, by
+updating the index and working tree to reflect the specified
+branch, <branch>, and updating HEAD to be <branch> or, if
+specified, <new_branch>.
+
+When <paths> are given, this command does *not* switch
+branches.  It updates the named paths in the working tree from
+the index file (i.e. it runs `git-checkout-index -f -u`).  In
+this case, `-f` and `-b` options are meaningless and giving
+either of them results in an error.  <branch> argument can be
+used to specify a specific tree-ish to update the index for the
+given paths before updating the working tree.
+
 
 OPTIONS
 -------
@@ -29,6 +41,30 @@ OPTIONS
 	Branch to checkout; may be any object ID that resolves to a
 	commit. Defaults to HEAD.
 
+
+EXAMPLE
+-------
+
+The following sequence checks out the `master` branch, reverts
+the `Makefile` to two revisions back, deletes hello.c by
+mistake, and gets it back from the index.
+
+------------
+$ git checkout master
+$ git checkout master~2 Makefile
+$ rm -f hello.c
+$ git checkout hello.c
+------------
+
+If you have an unfortunate branch that is named `hello.c`, the
+last step above would be confused as an instruction to switch to
+that branch.  You should instead write:
+
+------------
+$ git checkout -- hello.c
+------------
+
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
diff --git a/git-checkout.sh b/git-checkout.sh
index 2c053a3..73652fa 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -23,32 +23,81 @@ while [ "$#" != "0" ]; do
 	"-f")
 		force=1
 		;;
+	--)
+		break
+		;;
 	*)
-		rev=$(git-rev-parse --verify "$arg^0" 2>/dev/null) ||
-			die "I don't know any '$arg'."
-		if [ -z "$rev" ]; then
-			echo "unknown flag $arg"
-			exit 1
-		fi
-		if [ "$new" ]; then
-			echo "Multiple revisions?"
-			exit 1
-		fi
-		new="$rev"
-		if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
-			branch="$arg"
+		if rev=$(git-rev-parse --verify "$arg^0" 2>/dev/null)
+		then
+			if [ -z "$rev" ]; then
+				echo "unknown flag $arg"
+				exit 1
+			fi
+			new="$rev"
+			if [ -f "$GIT_DIR/refs/heads/$arg" ]; then
+				branch="$arg"
+			fi
+		elif rev=$(git-rev-parse --verify "$arg^{tree}" 2>/dev/null)
+		then
+			# checking out selected paths from a tree-ish.
+			new="$rev"
+			branch=
+		else
+			new=
+			branch=
+			set x "$arg" "$@"
+			shift
 		fi
+		break
 		;;
     esac
 done
-[ -z "$new" ] && new=$old
 
+# The behaviour of the command with and without explicit path
+# parameters is quite different.
+#
+# Without paths, we are checking out everything in the work tree,
+# possibly switching branches.  This is the traditional behaviour.
 #
+# With paths, we are _never_ switching branch, but checking out
+# the named paths from either index (when no rev is given),
+# or the named tree-ish (when rev is given).
+
+if test "$#" -ge 1
+then
+	if test '' != "$newbranch$force"
+	then
+		die "updating paths and switching branches or forcing are incompatible."
+	fi
+	if test '' != "$new"
+	then
+		# from a specific tree-ish; note that this is for
+		# rescuing paths and is never meant to remove what
+		# is not in the named tree-ish.
+		git-ls-tree -r "$new" "$@" |
+		sed -ne 's/^\([0-7]*\) blob \(.*\)$/\1 \2/p' |
+		git-update-index --index-info || exit $?
+	fi
+	git-checkout-index -f -u -- "$@"
+	exit $?
+else
+	# Make sure we did not fall back on $arg^{tree} codepath
+	# since we are not checking out from an arbitrary tree-ish,
+	# but switching branches.
+	if test '' != "$new"
+	then
+		git-rev-parse --verify "$new^{commit}" >/dev/null 2>&1 ||
+		die "Cannot switch branch to a non-commit."
+	fi
+fi
+
+[ -z "$new" ] && new=$old
+
 # If we don't have an old branch that we're switching to,
 # and we don't have a new branch name for the target we
 # are switching to, then we'd better just be checking out
 # what we already had
-#
+
 [ -z "$branch$newbranch" ] &&
 	[ "$new" != "$old" ] &&
 	die "git checkout: you need to specify a new branch name"
---
0.99.8.GIT

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2005-10-18  8:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-16 19:14 git-checkout-index, flag ordering and --prefix kludgy handling Blaisorblade
2005-10-17 22:58 ` Junio C Hamano
2005-10-17 22:58 ` Linus Torvalds
2005-10-18  0:33   ` Junio C Hamano
2005-10-18  1:28     ` Linus Torvalds
2005-10-18  2:27       ` Junio C Hamano
2005-10-18  2:48         ` Linus Torvalds
2005-10-18  5:49           ` Teach "git diff" to handle filenames startign with '-' Linus Torvalds
2005-10-18  5:57             ` Handle "-" at beginning of filenames, part 3 Linus Torvalds
2005-10-18  8:34         ` [PATCH] git-checkout: revert specific paths to either index or a given tree-ish Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).