threads / discuss / 2646

index manipulation -- how?

Subject: index manipulation -- how?

## tl;dr

7 messages between Nov 22, 2005 and Nov 22, 2005.

replies: 6people: 3as markdown or json

Luben Tuikov· Nov 22, 2005, 05:03 UTC · lore
I've a question:

Suppose I've updated the index and there is several updates pending in it: several new files, and several updates, etc.

That is a sequence of: git-update-index [options] <file> ...

My question is: How do I reverse a _single_ "git-update-index" operation? Be it --add or just an update.

Thanks,
    Luben
Linus Torvalds· Nov 22, 2005, 05:23 UTC · re: Luben Tuikov · lore

Re: index manipulation -- how?

On Mon, 21 Nov 2005, Luben Tuikov wrote:
> 
> How do I reverse a _single_ "git-update-index" operation?
> Be it --add or just an update.
An "add" is easy enough to undo: just do a
	git-update-index --force-remove filename

which will remove the entry from the index even if the file on your filesystem still remains (so you can "git add" it later when you do want to commit it).

For a file that you had in your old index, but you've updated (either mode or SHA1), you need to figure out what the old mode/sha1 was. USUALLY this would be just the state that you still have in your HEAD tree, but if you want to go back to something else, you'd need to figure out what that was.

If it's the "last commit" state (ie just your HEAD state), then do
	git-ls-tree HEAD filename
which will show you the info, and then you do
	git-update-index --cacheinfo <mode> <sha1> filename
from that state.
You could obviously script something like "git-downdate-index":
	#!/bin/sh
	filename="$1"
	tree_info=$(git-ls-tree HEAD -- "$filename")
	if [ -z "$tree_info" ]; then
		git-update-index --force-remove -- "$filename"
	else
		echo "$tree_info" | while read mode type sha1 name; do
			git-update-index --cacheinfo "$mode" "$sha1" "$filename"
		done
	fi

but the above is totally untested, and "git-downdate-index" is a really sucky name too, so you'd need to rename it and test whether it does what you want.

Hmm?
		Linus
Junio C Hamano· Nov 22, 2005, 05:24 UTC · re: Luben Tuikov · lore

Re: index manipulation -- how?

Luben Tuikov <ltuikov@yahoo.com> writes:
> How do I reverse a _single_ "git-update-index" operation?
> Be it --add or just an update.

Reverting working tree files are "git checkout HEAD the-file" (both index and working tree file from the head commit) or "git checkout -- the-file" (working tree file from the index), but I do not think there is a prepackaged way to revert only a single index path offhand.

        git-ls-tree HEAD the-file |
        sed -e 's/^\([0-7]*\) [^ ]* \(.*\)/\1 \2/' |
        git-update-index --index-info
should work.

I think changing update-index --index-info so that you can lose the sed in between without breaking its other usage (it reads from git-apply --index-info, which does not say " blob " which is what the sed is stripping out) is a worthwhile thing to do.

Junio C Hamano· Nov 22, 2005, 05:36 UTC · re: Junio C Hamano · lore

Re: index manipulation -- how?

Junio C Hamano <junkio@cox.net> writes:
Show 21 quoted lines
> Luben Tuikov <ltuikov@yahoo.com> writes:
>
>> How do I reverse a _single_ "git-update-index" operation?
>> Be it --add or just an update.
>
> Reverting working tree files are "git checkout HEAD the-file"
> (both index and working tree file from the head commit) or "git
> checkout -- the-file" (working tree file from the index), but I
> do not think there is a prepackaged way to revert only a single
> index path offhand.
>
>         git-ls-tree HEAD the-file |
>         sed -e 's/^\([0-7]*\) [^ ]* \(.*\)/\1 \2/' |
>         git-update-index --index-info
>
> should work.
>
> I think changing update-index --index-info so that you can lose
> the sed in between without breaking its other usage (it reads
> from git-apply --index-info, which does not say " blob " which
> is what the sed is stripping out) is a worthwhile thing to do.
And here is the patch to let you say:
	git-ls-tree HEAD the-file | git-update-index --index-info
---
diff --git a/update-index.c b/update-index.c
index 5bbc3de..11b7f6a 100644
--- a/update-index.c
+++ b/update-index.c
@@ -338,7 +338,7 @@ static void read_index_info(int line_ter
 	struct strbuf buf;
 	strbuf_init(&buf);
 	while (1) {
-		char *ptr;
+		char *ptr, *tab;
 		char *path_name;
 		unsigned char sha1[20];
 		unsigned int mode;
@@ -348,12 +348,15 @@ static void read_index_info(int line_ter
 			break;
 
 		mode = strtoul(buf.buf, &ptr, 8);
-		if (ptr == buf.buf || *ptr != ' ' ||
-		    get_sha1_hex(ptr + 1, sha1) ||
-		    ptr[41] != '\t')
+		if (ptr == buf.buf || *ptr != ' ')
 			goto bad_line;
 
-		ptr += 42;
+		tab = strchr(ptr, '\t');
+		if (!tab || tab - ptr < 41)
+			goto bad_line;
+		if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
+			goto bad_line;
+		ptr = tab + 1;
 
 		if (line_termination && ptr[0] == '"')
 			path_name = unquote_c_style(ptr, NULL);
Luben Tuikov· Nov 22, 2005, 06:20 UTC · re: Junio C Hamano · lore

Re: index manipulation -- how?

--- Junio C Hamano <junkio@cox.net> wrote:
Show 16 quoted lines
> Junio C Hamano <junkio@cox.net> writes:
> 
> > Luben Tuikov <ltuikov@yahoo.com> writes:
> >
> >> How do I reverse a _single_ "git-update-index" operation?
> >> Be it --add or just an update.
> >
> > Reverting working tree files are "git checkout HEAD the-file"
> > (both index and working tree file from the head commit) or "git
> > checkout -- the-file" (working tree file from the index), but I
> > do not think there is a prepackaged way to revert only a single
> > index path offhand.
> >
> >         git-ls-tree HEAD the-file |
> >         sed -e 's/^\([0-7]*\) [^ ]* \(.*\)/\1 \2/' |
> >         git-update-index --index-info

Ok. (There is a very similar construct in git-checkout.sh. So if you apply the patch below, please make sure git-checkout.sh doesn't break.)

Question: so in effect, more generally:
  git checkout <tree-ish> <file>

would do the right thing: update index and the working tree as the file <file> looked as it was at <tree-ish>?

Is that correct?  Can someone confirm/deny?
   Luben
P.S. So both methods as mentioned by Linus and Junio
do what I asked about.
Show 55 quoted lines
> >
> > should work.
> >
> > I think changing update-index --index-info so that you can lose
> > the sed in between without breaking its other usage (it reads
> > from git-apply --index-info, which does not say " blob " which
> > is what the sed is stripping out) is a worthwhile thing to do.
> 
> And here is the patch to let you say:
> 
> 	git-ls-tree HEAD the-file | git-update-index --index-info
> 
> 
> ---
> 
> diff --git a/update-index.c b/update-index.c
> index 5bbc3de..11b7f6a 100644
> --- a/update-index.c
> +++ b/update-index.c
> @@ -338,7 +338,7 @@ static void read_index_info(int line_ter
>  	struct strbuf buf;
>  	strbuf_init(&buf);
>  	while (1) {
> -		char *ptr;
> +		char *ptr, *tab;
>  		char *path_name;
>  		unsigned char sha1[20];
>  		unsigned int mode;
> @@ -348,12 +348,15 @@ static void read_index_info(int line_ter
>  			break;
>  
>  		mode = strtoul(buf.buf, &ptr, 8);
> -		if (ptr == buf.buf || *ptr != ' ' ||
> -		    get_sha1_hex(ptr + 1, sha1) ||
> -		    ptr[41] != '\t')
> +		if (ptr == buf.buf || *ptr != ' ')
>  			goto bad_line;
>  
> -		ptr += 42;
> +		tab = strchr(ptr, '\t');
> +		if (!tab || tab - ptr < 41)
> +			goto bad_line;
> +		if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
> +			goto bad_line;
> +		ptr = tab + 1;
>  
>  		if (line_termination && ptr[0] == '"')
>  			path_name = unquote_c_style(ptr, NULL);
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Junio C Hamano· Nov 22, 2005, 07:05 UTC · re: Luben Tuikov · lore

Re: index manipulation -- how?

Luben Tuikov <ltuikov@yahoo.com> writes:
> (There is a very similar construct in git-checkout.sh.
> So if you apply the patch below, please make sure
> git-checkout.sh doesn't break.)
Thanks.
Show 5 quoted lines
> Question: so in effect, more generally:
>   git checkout <tree-ish> <file>
>
> would do the right thing: update index and the working
> tree as the file <file> looked as it was at <tree-ish>?

Yes that is correct. Also by omitting <tree-ish> you can checkout from the index.

I thought what you originally wanted to do was revert only index without losing your changes from the working tree, so just to make sure, the above does _not_ do it --- the named file in the working tree is also reverted to the one from <tree-ish>.

Luben Tuikov· Nov 22, 2005, 07:35 UTC · re: Junio C Hamano · lore

Re: index manipulation -- how?

--- Junio C Hamano <junkio@cox.net> wrote:
Show 5 quoted lines
> 
> I thought what you originally wanted to do was revert only index
> without losing your changes from the working tree, so just to
> make sure, the above does _not_ do it --- the named file in the
> working tree is also reverted to the one from <tree-ish>.
Exactly what I want.
Thanks,
   Luben
P.S. I figured this one out in three stages:
Since checked out files are in rw- mode, but unchecked
files simply do not exist, first I want to "revert"
a changed file in the working tree -- this one is easy.
Then the second stage is if also the index is updated
(but no commit), and the last stage is if also
there is a commit, for which I think I know what to use.

← back to recent threads