Git development
 help / color / mirror / Atom feed
* Re: "git reset --hard" == "git checkout HEAD" == "git reset --hard HEAD" ???
From: Sitaram Chamarty @ 2009-01-03 12:27 UTC (permalink / raw)
  To: git
In-Reply-To: <7vprj4ae5y.fsf@gitster.siamese.dyndns.org>

On 2009-01-03, Junio C Hamano <gitster@pobox.com> wrote:
> Sitaram Chamarty <sitaramc@gmail.com> writes:
>
>>>> It seems we have 2 ways to blow away work we haven't
>>>> checked in yet then right?
>>>
>>> Wrong.
>>
>> Strictly as asked, yes, but what if he adds a "-f" to the
>> middle command, making it "git checkout -f HEAD"?  Wouldn't
>> that be the same as the others then?
>
> Yeah, but comparing reset and checkout misses a whole _dimension_ in the
> revision space continuum.

[snip]

> "checkout -f" and "reset --hard" work on different dimensions, and what
> they do intersect when (and only when) the <branch>/<commit> argument
> happen to be HEAD.  "checkout -f <another>" and "reset --hard <another>"
> will do quite different things.

I teach git sometimes (internally) in my job.  It seems to
me that people who don't like TMTOWTDI get stuck on this
"why are there 2 ways to do the same thing" aspect, even
after I explain all the *other* uses of the two commands to
show that they're actually quite different!

Your use of "dimension" and "degenerate case" gave me an
idea...  most of my audience have decent math skills, so I
bet they get it if I say these are like two quite different
functions that just happen to intersect at x=0 :-)

Thank you very much!

^ permalink raw reply

* Re: git reset --hard <commit> superfluous?
From: Björn Steinbrink @ 2009-01-03 12:20 UTC (permalink / raw)
  To: chris; +Cc: git
In-Reply-To: <20090103011319.GA24149@seberino.org>

On 2009.01.02 17:13:19 -0800, chris@seberino.org wrote:
> David
> 
> git reset --hard <commit>
> "resets" the current branch head.
> 
> Is this equivalent to deleting the branch
> and doing
> 
> git branch <branch> <commit> ??
> 
> So "git reset --hard" is syntactic sugar and 'unnecessary' right?

Deleting the branch also deletes the reflog, while using reset adds a
new entry to the reflog. So returning the branch head to its previous
state is pretty trivial if you used reset and might be pretty hard if
you deleted the branch. HEAD's reflog should probably have the right
entry as well, but chances are that it's hidden in a crapload of other
entries, especially if you rebase often.

Björn

^ permalink raw reply

* Re: git checkout does not warn about tags without corresponding commits
From: Junio C Hamano @ 2009-01-03 11:53 UTC (permalink / raw)
  To: Henrik Austad; +Cc: git, Daniel Barkalow
In-Reply-To: <7vr63k8vvf.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> I haven't looked at the code very closely, but I think this should fix
> it.  Thorough reviewing (not just running the test suite) is much
> appreciated.

Just for fun, this will apply to 782c2d6 (Build in checkout, 2008-02-07)
and seems to fix the issue ;-)

No, I am not going to issue a maintenance release for 1.5.5 just to
include this fix, even though I could.  I do not think this is a grave
enough regression to warrant a backport beyond 1.6.0 series.

 builtin-checkout.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git i/builtin-checkout.c w/builtin-checkout.c
index 59a0ef4..1d0de68 100644
--- i/builtin-checkout.c
+++ w/builtin-checkout.c
@@ -435,6 +435,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 			argv++;
 			argc--;
 		} else if ((source_tree = parse_tree_indirect(rev))) {
+			new.name = arg;
 			argv++;
 			argc--;
 		}

^ permalink raw reply related

* Re: git checkout does not warn about tags without corresponding commits
From: Junio C Hamano @ 2009-01-03 11:36 UTC (permalink / raw)
  To: Henrik Austad; +Cc: git, Daniel Barkalow
In-Reply-To: <200901031200.01883.henrik@austad.us>

Henrik Austad <henrik@austad.us> writes:

> On Friday 02 January 2009 22:44:50 Junio C Hamano wrote:
>> Henrik Austad <henrik@austad.us> writes:
>> > I recently tried to do a checkout of (what I thought was the first) inux
>> > kernel in the linux git repo.
>> >
>> > git checkout -b 2.6.11 v2.6.11
>>
>> This should have barfed, and indeed I think it is a regression around
>> v1.5.5.  v1.5.4 and older git definitely fails to check out a tree object
>> like that.
>
> You're right, I bisected it down to commit 
> 782c2d65c24066a5d83453efb52763bc34c10f81

I am not surprised.

That one discarded an implementation of "git checkout" in Bourne shell,
with a complete reimplementation in C.

I haven't looked at the code very closely, but I think this should fix
it.  Thorough reviewing (not just running the test suite) is much
appreciated.

-- >8 --
Subject: git-checkout: do not allow switching to a tree-ish

"git checkout -b newbranch $commit^{tree}" mistakenly created a new branch
rooted at the current HEAD, because in that case, the two structure fields
used to see if the command was invoked without any argument (hence it
needs to default to checking out the HEAD), were populated incorrectly.

Upon seeing a command line argument that we took as a rev, we should store
that string in new.name, even if that does not name a commit.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-checkout.c               |    2 +-
 t/t2011-checkout-invalid-head.sh |    4 ++++
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git c/builtin-checkout.c w/builtin-checkout.c
index c2c0561..b5dd9c0 100644
--- c/builtin-checkout.c
+++ w/builtin-checkout.c
@@ -681,8 +681,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		argv++;
 		argc--;
 
+		new.name = arg;
 		if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
-			new.name = arg;
 			setup_branch_path(&new);
 			if (resolve_ref(new.path, rev, 1, NULL))
 				new.commit = lookup_commit_reference(rev);
diff --git c/t/t2011-checkout-invalid-head.sh w/t/t2011-checkout-invalid-head.sh
index 764bb0a..798790d 100755
--- c/t/t2011-checkout-invalid-head.sh
+++ w/t/t2011-checkout-invalid-head.sh
@@ -15,4 +15,8 @@ test_expect_success 'checkout master from invalid HEAD' '
 	git checkout master --
 '
 
+test_expect_success 'checkout should not start branch from a tree' '
+	test_must_fail git checkout -b newbranch master^{tree}
+'
+
 test_done

^ permalink raw reply related

* Re: git checkout does not warn about tags without corresponding commits
From: Henrik Austad @ 2009-01-03 11:00 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8wptcrhp.fsf@gitster.siamese.dyndns.org>

[-- Attachment #1: Type: text/plain, Size: 836 bytes --]

On Friday 02 January 2009 22:44:50 Junio C Hamano wrote:
> Henrik Austad <henrik@austad.us> writes:
> > I recently tried to do a checkout of (what I thought was the first) inux
> > kernel in the linux git repo.
> >
> > git checkout -b 2.6.11 v2.6.11
>
> This should have barfed, and indeed I think it is a regression around
> v1.5.5.  v1.5.4 and older git definitely fails to check out a tree object
> like that.

You're right, I bisected it down to commit 
782c2d65c24066a5d83453efb52763bc34c10f81

It introduces quite a large change, adding checkout-builtin.c, which coud be 
the cause I guess.

As of how to fix this (if a fix is desired) I have not yet any clue what so 
ever :-)

I attached the bisect result (sorry if attachements are frowned upon, but my 
email client tends to mutilate text-contents like that).

-- 
 -> henrik

[-- Attachment #2: git_bisect_res.txt --]
[-- Type: text/plain, Size: 2270 bytes --]

782c2d65c24066a5d83453efb52763bc34c10f81 is first bad commit
commit 782c2d65c24066a5d83453efb52763bc34c10f81
Author: Daniel Barkalow <barkalow@iabervon.org>
Date:   Thu Feb 7 11:40:23 2008 -0500

    Build in checkout

    The only differences in behavior should be:

     - git checkout -m with non-trivial merging won't print out
       merge-recursive messages (see the change in t7201-co.sh)

     - git checkout -- paths... will give a sensible error message if
       HEAD is invalid as a commit.

     - some intermediate states which were written to disk in the shell
       version (in particular, index states) are only kept in memory in
       this version, and therefore these can no longer be revealed by
       later write operations becoming impossible.

     - when we change branches, we discard MERGE_MSG, SQUASH_MSG, and
       rr-cache/MERGE_RR, like reset always has.

    I'm not 100% sure I got the merge recursive setup exactly right; the
    base for a non-trivial merge in the shell code doesn't seem
    theoretically justified to me, but I tried to match it anyway, and the
    tests all pass this way.

    Other than these items, the results should be identical to the shell
    version, so far as I can tell.

    [jc: squashed lock-file fix from Dscho in]

    Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
    Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:100644 100644 5cfadfd307d588a427e200576ba97a5227653a13 90c0dd8c43cd66008d29492bdfb6b21a17855a00 M      Makefile
:000000 100644 0000000000000000000000000000000000000000 59a0ef4ec9770af6d031abe959adc587c9538a89 A      builtin-checkout.c
:100644 100644 428160d0e48b2acf1ac54d6d73910fd93151ca22 25d91bbfb21ea3c1ea067b10f7ea033d3563936a M      builtin.h
:040000 040000 098e84f3f9fc152debb0f92eb849127f460391d7 0860a331e5a98a88a143d32f371385e78a0121d8 M      contrib
:100755 000000 5621c69d86062c7c75c0b8c2749d34efc78cafb4 0000000000000000000000000000000000000000 D      git-checkout.sh
:100644 100644 114ea75eef55e2960ff111014a505c3eb678caae fc156863b0bbd7d264864c49c2529e47709abf4d M      git.c
:040000 040000 49b19f06ce0395f99f5b9729a1e51b5fa7fd1875 4165e146453fa357ef5e76a9ad48e683301ae669 M      t


^ permalink raw reply

* Re: [PATCH 2/3] unpack-trees: fix path search bug in verify_absent
From: Clemens Buchacher @ 2009-01-03 10:39 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, gitster
In-Reply-To: <alpine.DEB.1.00.0901022248070.27818@racer>

On Fri, Jan 02, 2009 at 10:59:47PM +0100, Johannes Schindelin wrote:
> This explanation makes sense.  However, this:
> 
> > @@ -289,7 +289,8 @@ static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmas
> >  	return 0;
> >  }
> >  
> > -static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
> > +static int unpack_callback(int n, unsigned long mask, unsigned long dirmask,
> > +		struct name_entry *names, struct traverse_info *info)
> >  {
> >  	struct cache_entry *src[5] = { NULL, };
> >  	struct unpack_trees_options *o = info->data;
> 
> ... is distracting during review, and this:
> 
> > @@ -517,22 +518,22 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
> >  	namelen = strlen(ce->name);
> >  	pos = index_name_pos(o->src_index, ce->name, namelen);
> >  	if (0 <= pos)
> > -		return cnt; /* we have it as nondirectory */
> > +		return 0; /* we have it as nondirectory */
> >  	pos = -pos - 1;
> >  	for (i = pos; i < o->src_index->cache_nr; i++) {
> 
> ... is not accounted for in the commit message.  Intended or not, that is 
> the question.

Those are trivial readability improvements in the context of the patch.

On Fri, Jan 02, 2009 at 10:59:43PM +0100, Johannes Schindelin wrote:
> Sign-off?

Signed-off-by: Clemens Buchacher <drizzd@aon.at>

on all three patches.

^ permalink raw reply

* Re: What's cooking in git.git (Dec 2008, #04; Mon, 29)
From: Junio C Hamano @ 2009-01-03 10:31 UTC (permalink / raw)
  To: Christian Couder; +Cc: git
In-Reply-To: <200901030640.36426.chriscool@tuxfamily.org>

Christian Couder <chriscool@tuxfamily.org> writes:

> Le mardi 30 décembre 2008, Junio C Hamano a écrit :
>>
>> * cc/bisect-replace (Mon Nov 24 22:20:30 2008 +0100) 9 commits
>>  - bisect: add "--no-replace" option to bisect without using replace
>>    refs
>>  - rev-list: make it possible to disable replacing using "--no-
>>    bisect-replace"
>>  - bisect: use "--bisect-replace" options when checking merge bases
>>  - merge-base: add "--bisect-replace" option to use fixed up revs
>>  - commit: add "bisect_replace_all" prototype to "commit.h"
>>  - rev-list: add "--bisect-replace" to list revisions with fixed up
>>    history
>>  - Documentation: add "git bisect replace" documentation
>>  - bisect: add test cases for "git bisect replace"
>>  - bisect: add "git bisect replace" subcommand
>>
>> I think a mechanism like this should be added to replace grafts, 
>
> The problem with replacing grafts is that a graft can specify many parents 
> for one commit while a ref associates only one object to a name.

Sorry, maybe I misunderstood your implementation.  What I thought we
discussed during GitTogether was to write out the object name of the
replacement object in refs/replace/<sha1>.

When the caller asks read_sha1_file() for an object whose object name is
<sha1>, you see if there is refs/replace/<sha1> in the repository, and
read the ref to learn the object name of the object that replaces it.  And
you return that as if it is the original object.

So if your commit cca1704897e7fdb182f68d4c48a437c5d7bc5203 looks like:

    tree 7ccf394b2e80536442703e0013bf0dde86547e08
    parent 3827210b91a7d363ea67bcf0b9c6ee1c91d2f3c5
    author Johannes Schindelin <Johannes.Schindelin@gmx.de> 1230919672 +0100
    committer Junio C Hamano <gitster@pobox.com> 1230931180 -0800

    git wrapper: Make while loop more reader-friendly
    ...

and you would want to lie about its author (or add/subtract different
parent lines, or record a fixed-up tree, or whatever), you first prepare a
replacement commit object:

    $ R=$(git cat-file commit cca17048 |
      sed -e 's/Johannes /&E /' |
      git hash-object -t commit --stdin -w)
    $ git cat-file commit $R
    tree 7ccf394b2e80536442703e0013bf0dde86547e08
    parent 3827210b91a7d363ea67bcf0b9c6ee1c91d2f3c5
    author Johannes E Schindelin <Johannes.Schindelin@gmx.de> 1230919672 +0100
    committer Junio C Hamano <gitster@pobox.com> 1230931180 -0800

    git wrapper: Make while loop more reader-friendly
    ...

and then tell git to replace the original object with this one:

    $ git update-ref refs/replace/$(git rev-parse cca17048) $R

With such a layout, if your arrange the object reachability traverser
(e.g. fsck, pack-objects, bundle and prune) ignore refs/replace mechanism,
while everybody else pay attention to it, you will be able to safely
transfer the "graft" information via usual clone/fetch/push mechanism,
while making things like log, bisect and show just work, pretending as if
the commit cca17048 were made by JES and not by JS.

^ permalink raw reply

* Re: "git reset --hard" == "git checkout HEAD" == "git reset --hard HEAD" ???
From: Junio C Hamano @ 2009-01-03 10:15 UTC (permalink / raw)
  To: Sitaram Chamarty; +Cc: git
In-Reply-To: <slrngltvrd.63u.sitaramc@sitaramc.homelinux.net>

Sitaram Chamarty <sitaramc@gmail.com> writes:

>>> It seems we have 2 ways to blow away work we haven't
>>> checked in yet then right?
>>
>> Wrong.
>
> Strictly as asked, yes, but what if he adds a "-f" to the
> middle command, making it "git checkout -f HEAD"?  Wouldn't
> that be the same as the others then?

Yeah, but comparing reset and checkout misses a whole _dimension_ in the
revision space continuum.

"git checkout <branch>" is primarily about checking out a different
branch, aka "switching branches".

When you switch branches, you generally do not want to lose your pending
changes, but would want to take them with you.  A typical scenario is that
you start looking at one issue, you fiddle a few lines here and twiddle a
few lines there, and as you dig deeper, you realize that whatever the
final shape of the change you are going to make will be either (1) big
enough to deserve its own branch created anew, or (2) better done as an
extension to an existing branch.  You realize that you are in the latter
situation by noticing that the modification you were making will be helped
by something you have implemented in the other branch but not yet
available in the current one (typically the latter is 'master').

In such a case, you will "git checkout <the-appropriate-topic>" to switch
to the branch, and you would want to take the change you already made to
your work tree files when you do so.

On the other hand, "git checkout -f <branch>" blows away your changes, but
it still _is_ about switching to a different branch.

Whether you use -f or not, you are allowed to ask to switch to the current
branch by (1) naming the branch explicitly, i.e. "git checkout -f master",
(2) using HEAD to mean the current one instead, or (3) omitting <branch>
altogether.  But that is there merely for consistency and, even though
there may not make much sense to do so (because it is largely no-op except
that you would get the "you are ahead by N" notice), there is no strong
reason to forbid asking for a no-op.

For that reason, "git checkout -f HEAD" is "blow away my changes".  But it
is merely a degenerated case of "switching to the current branch while
blowing away my changes."

"git reset --hard <commit>" is different.  "reset" is primarily about
pointing the tip of the current branch to somewhere else.  While "git
checkout <branch>" never changes what commit sits at the tip of any
branch, "git reset <commit>" modifies it for the current branch (--hard
variant matches the work tree files to the contents recorded by the
resetted-to commit while at it).

Again, you are allowed to ask to reset to the current HEAD by saying
"reset --hard HEAD".  That is a degenerated case of "resetting the tip of
the current branch, while blowing away my changes".  More general case
would be "reset --hard <some-commit>" and it won't just blow away your
changes (relative to the commit you started out with), but also blows away
the history leading to the commit the branch tip used to point at.

"checkout -f" and "reset --hard" work on different dimensions, and what
they do intersect when (and only when) the <branch>/<commit> argument
happen to be HEAD.  "checkout -f <another>" and "reset --hard <another>"
will do quite different things.

^ permalink raw reply

* Re: git reset --hard <commit> superfluous?
From: Sitaram Chamarty @ 2009-01-03  6:34 UTC (permalink / raw)
  To: git
In-Reply-To: <20090103011319.GA24149@seberino.org>

On 2009-01-03, chris@seberino.org <chris@seberino.org> wrote:
> git reset --hard <commit>
> "resets" the current branch head.
>
> Is this equivalent to deleting the branch
> and doing
>
> git branch <branch> <commit> ??
>
> So "git reset --hard" is syntactic sugar and 'unnecessary' right?

only if you don't have any local changes to the work tree or
the index :-)

If you do, however, the reset throws them away, while the
longer method tries to preserves them, to the point of not
letting you switch if there are too many changes.

^ permalink raw reply

* Re: What's cooking in git.git (Dec 2008, #04; Mon, 29)
From: Christian Couder @ 2009-01-03  5:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vocyt1is2.fsf@gitster.siamese.dyndns.org>

Le mardi 30 décembre 2008, Junio C Hamano a écrit :
>
> * cc/bisect-replace (Mon Nov 24 22:20:30 2008 +0100) 9 commits
>  - bisect: add "--no-replace" option to bisect without using replace
>    refs
>  - rev-list: make it possible to disable replacing using "--no-
>    bisect-replace"
>  - bisect: use "--bisect-replace" options when checking merge bases
>  - merge-base: add "--bisect-replace" option to use fixed up revs
>  - commit: add "bisect_replace_all" prototype to "commit.h"
>  - rev-list: add "--bisect-replace" to list revisions with fixed up
>    history
>  - Documentation: add "git bisect replace" documentation
>  - bisect: add test cases for "git bisect replace"
>  - bisect: add "git bisect replace" subcommand
>
> I think a mechanism like this should be added to replace grafts, 

The problem with replacing grafts is that a graft can specify many parents 
for one commit while a ref associates only one object to a name.

One way to overcome this could be to use many refs for each graft, for 
example (in the packed ref format):

<1st parent sha1> refs/replace/grafts/<commit sha1>-<1st parent sha1>
<2nd parent sha1> refs/replace/grafts/<commit sha1>-<2nd parent sha1>
...

Another way would be to put all the parents in the ref name, for example:

<1st parent sha1> /refs/replace/grafts/<commit sha1>-<1st parent sha1>-<2nd 
parent sha1>-<3rd parent sha1>

There is the same kind of problem to mark many "good" (and "skip") commits 
when bisecting and we use something like the first solution above:

<1st good commit sha1> refs/bisect/good-<1st good commit sha1>
<2nd good commit sha1> refs/bisect/good-<2nd good commit sha1>
...

But I think the above solutions are not very clean and it might be better in 
the long run to make it possible to associate more than one object to a 
ref.

Am I missing something? Do you see another way?

Thanks and happy new year everybody,
Christian.

^ permalink raw reply

* Re: "git reset --hard" == "git checkout HEAD" == "git reset --hard HEAD" ???
From: Sitaram Chamarty @ 2009-01-03  6:02 UTC (permalink / raw)
  To: git
In-Reply-To: <7v4p0hcp3w.fsf@gitster.siamese.dyndns.org>

On 2009-01-02, Junio C Hamano <gitster@pobox.com> wrote:
> chris@seberino.org writes:
>
>> Does "git reset --hard" == "git checkout HEAD" == "git reset --hard HEAD" ???
>
> No, but "reset --hard" without a commit-ish defaults to HEAD so the first
> one and the last one are equivalent.
>
>> It seems we have 2 ways to blow away work we haven't
>> checked in yet then right?
>
> Wrong.

Strictly as asked, yes, but what if he adds a "-f" to the
middle command, making it "git checkout -f HEAD"?  Wouldn't
that be the same as the others then?

I always thought they were eqvt...

^ permalink raw reply

* [PATCH] fast-export: print usage when no options specified
From: Miklos Vajna @ 2009-01-03  3:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, jidanni, git
In-Reply-To: <87r63lus6k.fsf@jidanni.org>

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---

I found that behaviour surprising as well when I saw it the first time.
git rev-list outputs some usage info in that case, git log just logs
HEAD. Given that unconditionally exporting HEAD with no arguments is
probably not something most users want, here is a patch to make the
behaviour like what git rev-list already has.

 builtin-fast-export.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 8386338..e9ee2c7 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -497,6 +497,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
+	if (argc == 1)
+		usage_with_options (fast_export_usage, options);
+
 	/* we handle encodings */
 	git_config(git_default_config, NULL);
 
-- 
1.6.1

^ permalink raw reply related

* Re: how to track the history of a line in a file
From: david @ 2009-01-03  4:25 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <alpine.DEB.1.10.0901021554581.21567@asgard.lang.hm>

On Fri, 2 Jan 2009, david@lang.hm wrote:

> On Fri, 2 Jan 2009, david@lang.hm wrote:
>
>> On Fri, 2 Jan 2009, david@lang.hm wrote:
>> 
>>> On Fri, 2 Jan 2009, Jeff King wrote:
>>> 
>>>> The tricky thing here is what is "this line"? Using the line number
>>>> isn't right, since it will change based on other content coming in and
>>>> out of the file. You can keep drilling down by reblaming parent commits,
>>>> but remember that each time you do that you are manually looking at the
>>>> content and saying "Oh, this is the line I am still interested in." So I
>>>> a script would have to correlate the old version and new version of the
>>>> line and realize how to follow the "interesting" thing.
>>>> 
>>>> In your case, I think you want to see any commit in Makefile which
>>>> changed a line with SUBLEVEL in it. Which is maybe easiest done as:
>>>>
>>>>  git log -z -p Makefile |
>>>>    perl -0ne 'print if /\n[+-]SUBLEVEL/' |
>>>>    tr '\0' '\n'
>>>> 
>>>> and is pretty fast. But obviously we're leveraging some content-specific
>>>> knowledge about what's in the Makefile.
>>> 
>>> Ok, I hacked togeather a quick bash script to try this
>>> 
>> <SNIP>
>>> the problem that this has is that line 3 of $COMMIT may not be line 3 of 
>>> $COMMIT^, and if they aren't it ends up hunting down the wrong data

solving this problem was a bit more work than expected. I ended up 
invoking git diff to do the step back and find what lines were replaced by 
the one I care about.

this still can run into problems if the lines that are examined are not 
unique (git blame only finds the first match)



#!/usr/bin/perl
# program to trace the history of a line through a git repository
#
# useage findlines pattern filespec
#
# finds all occurances of the pattern in the file and then uses git blame
#  to find where those lines were introduced. It then takes a step back 
and
#  looks at what the line replaced (if anything) and does a git blame on 
those
#  lines as well
#
# written by David Lang and released under GPLv2
#
$target = shift @ARGV;
$file = shift @ARGV;
open($infile,"<$file");
$linecount=0;
# find all lines in the file that match the target pattern
# we have been provided. add them to a stack of items to research
while(<$infile>){
   $linecount++;
   if ($_ =~ /$target/) {
     $items[++$#items]{line} = $linecount;
     $items[$#items]{tree} = "HEAD";
     chomp;
     $items[$#items]{target} = $_;
   }
}
# go through all the items and research them in turn
#  (note that more items may be added to the list while inside this loop)
for ($i=0;$i<=$#items;$i++) {
# do a git blame to find where the lines came from
   $result = `git blame -b -l -L "$items[$i]{line}",+1 -M  $file 
$items[$i]{tree}` ;
   print "in ".$items[$i]{tree}." found:\n$result";
   $commit=substr($result,0,40);
   # if this is not the root commit,
   #  do a diff to find what lines may have been replaced by the line we 
are looking for
   if($commit ne "                                        "){
     $diff=`git diff -U0 $commit^..$commit $file`;
     @lines=split("\n",$diff);
     #strip the first four lines from the diff (as they just talk about the 
file)
     shift(@lines);
     shift(@lines);
     shift(@lines);
     shift(@lines);
     $match=0;
     $hunk='';
     # find what hunk of the diff introduced the lines we are looking for,
     #  add the lines that they replaced to the list of items to examine
     foreach(@lines){
       if ($_ =~ /^\@\@/ ) {
         if ($match) {
           process_hunk();
         } else {
           $hunk = '';
         };
       } else {
         $hunk .= $_."\n";
         if ($_ =~ /$items[$i]{target}/) {
           $match = 1;
         }
       }
     }
     if ($match) {
       process_hunk();
     }
   }
}
sub process_hunk(){
   # find lines in the hunk of diff that are being replaced
   foreach (split("\n",$hunk)){
     if ($_ =~ /^-/ ){
       # for now queue the line contents for further processing.
       #   this really should be the line number becouse otherwise
       #   git blame will use the first match it finds. since we are
       # matching the entire line this is less of a problem than it could 
be.
       $items[++$#items]{line} = "/".substr($_,1)."/";
       $items[$#items]{target} = substr($_,1);
       $items[$#items]{tree} = "$commit^";
     }
   }
}

^ permalink raw reply

* git reset --hard <commit> superfluous?
From: chris @ 2009-01-03  1:13 UTC (permalink / raw)
  To: git

David

git reset --hard <commit>
"resets" the current branch head.

Is this equivalent to deleting the branch
and doing

git branch <branch> <commit> ??

So "git reset --hard" is syntactic sugar and 'unnecessary' right?

cs

^ permalink raw reply

* Re: how to track the history of a line in a file
From: david @ 2009-01-03  2:05 UTC (permalink / raw)
  To: Thomas Rast; +Cc: Junio C Hamano, Jeff King, git
In-Reply-To: <200901030107.07228.trast@student.ethz.ch>

On Sat, 3 Jan 2009, Thomas Rast wrote:

> david@lang.hm wrote:
>> On Fri, 2 Jan 2009, Junio C Hamano wrote:
>>> You may find the --porcelain output format of git-blame useful to make
>>> your script safer and more robust.
>>
>> where is this output defined? I can look at it and understand it, but I
>> don't know what is guarenteeded to exist, what will be on a specific line,
>> and what may vanish on me.
>
> man git-blame | less -p PORCELAIN\ FORMAT

thanks,

am I missing something else or will git blame with a regex only return 
info on the first line it matches?

David Lang

^ permalink raw reply

* git-fast-export bundle doc
From: jidanni @ 2009-01-03  0:52 UTC (permalink / raw)
  To: git

Please improve git-fast-export.txt. It says

       This program dumps the given revisions in a form suitable to be
       piped into git-fast-import.

<revlist> isn't mentioned in the SYNOPSIS.
And there is no hyperlink to the git-fast-import man page, nor in SEE ALSO.)

       You can use it as a human readable bundle replacement (see
       git-bundle(1))

But I tried it and there are apparently a few steps not mentioned that
are needed after git-fast-import before you can actually see the files
again on the other side of the sneakernet.

I used --all, which is in EXAMPLES but not OPTIONS.

Else nothing happens and no error is caught:
$ git fast-export
$

Also the git-bundle man page should SEE ALSO git-fast-export and maybe
even git-fast-import, which itself makes no mention of git-fast-export.

^ permalink raw reply

* Re: how to track the history of a line in a file
From: Thomas Rast @ 2009-01-03  0:07 UTC (permalink / raw)
  To: david; +Cc: Junio C Hamano, Jeff King, git
In-Reply-To: <alpine.DEB.1.10.0901021658330.21567@asgard.lang.hm>

[-- Attachment #1: Type: text/plain, Size: 468 bytes --]

david@lang.hm wrote:
> On Fri, 2 Jan 2009, Junio C Hamano wrote:
> > You may find the --porcelain output format of git-blame useful to make
> > your script safer and more robust.
> 
> where is this output defined? I can look at it and understand it, but I 
> don't know what is guarenteeded to exist, what will be on a specific line, 
> and what may vanish on me.

man git-blame | less -p PORCELAIN\ FORMAT

-- 
Thomas Rast
trast@{inf,student}.ethz.ch


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: how to track the history of a line in a file
From: david @ 2009-01-03  0:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <7vvdsxb9oh.fsf@gitster.siamese.dyndns.org>

On Fri, 2 Jan 2009, Junio C Hamano wrote:

> david@lang.hm writes:
>
>> I was misunderstanding git blame
>
> You may find the --porcelain output format of git-blame useful to make
> your script safer and more robust.

where is this output defined? I can look at it and understand it, but I 
don't know what is guarenteeded to exist, what will be on a specific line, 
and what may vanish on me.

David Lang

^ permalink raw reply

* [PATCH v3.1] rebase: learn to rebase root commit
From: Thomas Rast @ 2009-01-02 23:45 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <7vljttb95u.fsf@gitster.siamese.dyndns.org>

Teach git-rebase a new option --root, which instructs it to rebase the
entire history leading up to <branch>.  This option must be used with
--onto <newbase>, and causes commits that already exist in <newbase>
to be skipped.  (Normal operation skips commits that already exist in
<upstream> instead.)

The main use-case is with git-svn: suppose you start hacking (perhaps
offline) on a new project, but later notice you want to commit this
work to SVN.  You will have to rebase the entire history, including
the root commit, on a (possibly empty) commit coming from git-svn, to
establish a history connection.  This previously had to be done by
cherry-picking the root commit manually.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>

---

Junio C Hamano wrote:
> 
> >  # If a hook exists, give it a chance to interrupt
> > -run_pre_rebase_hook ${1+"$@"}
> > +run_pre_rebase_hook $root_flag $upstream_name "$@"
> 
> You'd have to quote the $upstream_name properly here, because the original
> command line could well have been:
> 
> 	$ git rebase 'master@{3 days ago}'

Right, thanks.  Let's fix it like this, so I won't have to look up
what the various special parameter expansion characters mean.
($root_flag is still used further below.)

>> --- a/git-rebase.sh
>> +++ b/git-rebase.sh
>> @@ -355,11 +355,13 @@ if test -z "$rebase_root"; then
>>         upstream=`git rev-parse --verify "${upstream_name}^0"` ||
>>         die "invalid upstream $upstream_name"
>>         unset root_flag
>> +       upstream_arg="$upstream_name"
>>  else
>>         test -z "$newbase" && die "--root must be used with --onto"
>>         unset upstream_name
>>         unset upstream
>>         root_flag="--root"
>> +       upstream_arg="$root_flag"
>>  fi
>>  
>>  # Make sure the branch to rebase onto is valid.
>> @@ -367,7 +369,7 @@ onto_name=${newbase-"$upstream_name"}
>>  onto=$(git rev-parse --verify "${onto_name}^0") || exit
>>  
>>  # If a hook exists, give it a chance to interrupt
>> -run_pre_rebase_hook $root_flag $upstream_name "$@"
>> +run_pre_rebase_hook "$upstream_arg" "$@"
>>  
>>  # If the branch to rebase is given, that is the branch we will rebase
>>  # $branch_name -- branch being rebased, or HEAD (already detached)

 git-rebase.sh          |   52 ++++++++++++++++++++--------
 t/t3412-rebase-root.sh |   86 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 15 deletions(-)

diff --git a/git-rebase.sh b/git-rebase.sh
index ebd4df3..d1083f1 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano.
 #
 
-USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
+USAGE='[--interactive | -i] [-v] [--onto <newbase>] [<upstream>|--root] [<branch>]'
 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
 same name.  When the --onto option is provided the new branch starts
 out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
@@ -47,6 +47,7 @@ dotest="$GIT_DIR"/rebase-merge
 prec=4
 verbose=
 git_am_opt=
+rebase_root=
 
 continue_merge () {
 	test -n "$prev_head" || die "prev_head must be defined"
@@ -297,6 +298,9 @@ do
 	-C*)
 		git_am_opt="$git_am_opt $1"
 		;;
+	--root)
+		rebase_root=t
+		;;
 	-*)
 		usage
 		;;
@@ -344,17 +348,28 @@ case "$diff" in
 	;;
 esac
 
+if test -z "$rebase_root"; then
 # The upstream head must be given.  Make sure it is valid.
-upstream_name="$1"
-upstream=`git rev-parse --verify "${upstream_name}^0"` ||
-    die "invalid upstream $upstream_name"
+	upstream_name="$1"
+	shift
+	upstream=`git rev-parse --verify "${upstream_name}^0"` ||
+	die "invalid upstream $upstream_name"
+	unset root_flag
+	upstream_arg="$upstream_name"
+else
+	test -z "$newbase" && die "--root must be used with --onto"
+	unset upstream_name
+	unset upstream
+	root_flag="--root"
+	upstream_arg="$root_flag"
+fi
 
 # Make sure the branch to rebase onto is valid.
 onto_name=${newbase-"$upstream_name"}
 onto=$(git rev-parse --verify "${onto_name}^0") || exit
 
 # If a hook exists, give it a chance to interrupt
-run_pre_rebase_hook ${1+"$@"}
+run_pre_rebase_hook "$upstream_arg" "$@"
 
 # If the branch to rebase is given, that is the branch we will rebase
 # $branch_name -- branch being rebased, or HEAD (already detached)
@@ -362,16 +377,16 @@ run_pre_rebase_hook ${1+"$@"}
 # $head_name -- refs/heads/<that-branch> or "detached HEAD"
 switch_to=
 case "$#" in
-2)
+1)
 	# Is it "rebase other $branchname" or "rebase other $commit"?
-	branch_name="$2"
-	switch_to="$2"
+	branch_name="$1"
+	switch_to="$1"
 
-	if git show-ref --verify --quiet -- "refs/heads/$2" &&
-	   branch=$(git rev-parse -q --verify "refs/heads/$2")
+	if git show-ref --verify --quiet -- "refs/heads/$1" &&
+	   branch=$(git rev-parse -q --verify "refs/heads/$1")
 	then
-		head_name="refs/heads/$2"
-	elif branch=$(git rev-parse -q --verify "$2")
+		head_name="refs/heads/$1"
+	elif branch=$(git rev-parse -q --verify "$1")
 	then
 		head_name="detached HEAD"
 	else
@@ -393,7 +408,8 @@ case "$#" in
 esac
 orig_head=$branch
 
-# Now we are rebasing commits $upstream..$branch on top of $onto
+# Now we are rebasing commits $upstream..$branch (or with --root,
+# everything leading up to $branch) on top of $onto
 
 # Check if we are already based on $onto with linear history,
 # but this should be done only when upstream and onto are the same.
@@ -429,10 +445,16 @@ then
 	exit 0
 fi
 
+if test ! -z "$rebase_root"; then
+	revisions="$onto..$orig_head"
+else
+	revisions="$upstream..$orig_head"
+fi
+
 if test -z "$do_merge"
 then
 	git format-patch -k --stdout --full-index --ignore-if-in-upstream \
-		"$upstream..$orig_head" |
+		$root_flag "$revisions" |
 	git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
 	move_to_original_branch
 	ret=$?
@@ -455,7 +477,7 @@ echo "$orig_head" > "$dotest/orig-head"
 echo "$head_name" > "$dotest/head-name"
 
 msgnum=0
-for cmt in `git rev-list --reverse --no-merges "$upstream..$orig_head"`
+for cmt in `git rev-list --reverse --no-merges "$revisions"`
 do
 	msgnum=$(($msgnum + 1))
 	echo "$cmt" > "$dotest/cmt.$msgnum"
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
new file mode 100755
index 0000000..1978512
--- /dev/null
+++ b/t/t3412-rebase-root.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+test_description='git rebase --root
+
+Tests if git rebase --root --onto <newparent> can rebase the root commit.
+'
+. ./test-lib.sh
+
+test_expect_success 'prepare repository' '
+	echo 1 > A &&
+	git add A &&
+	git commit -m 1 &&
+	echo 2 > A &&
+	git add A &&
+	git commit -m 2 &&
+	git symbolic-ref HEAD refs/heads/other &&
+	rm .git/index &&
+	echo 1 > A &&
+	git add A &&
+	git commit -m 1b &&
+	echo 3 > B &&
+	git add B &&
+	git commit -m 3 &&
+	echo 4 > B &&
+	git add B &&
+	git commit -m 4
+'
+
+test_expect_success 'rebase --root expects --onto' '
+	test_must_fail git rebase --root
+'
+
+test_expect_success 'setup pre-rebase hook' '
+	mkdir -p .git/hooks &&
+	cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+echo "\$1,\$2" >.git/PRE-REBASE-INPUT
+EOF
+	chmod +x .git/hooks/pre-rebase
+'
+cat > expect <<EOF
+4
+3
+2
+1
+EOF
+
+test_expect_success 'rebase --root --onto <newbase>' '
+	git checkout -b work &&
+	git rebase --root --onto master &&
+	git log --pretty=tformat:"%s" > rebased &&
+	test_cmp expect rebased
+'
+
+test_expect_success 'pre-rebase got correct input (1)' '
+	test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,
+'
+
+test_expect_success 'rebase --root --onto <newbase> <branch>' '
+	git branch work2 other &&
+	git rebase --root --onto master work2 &&
+	git log --pretty=tformat:"%s" > rebased2 &&
+	test_cmp expect rebased2
+'
+
+test_expect_success 'pre-rebase got correct input (2)' '
+	test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work2
+'
+
+test_expect_success 'setup pre-rebase hook that fails' '
+	mkdir -p .git/hooks &&
+	cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+false
+EOF
+	chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook stops rebase' '
+	git checkout -b stops1 other &&
+	GIT_EDITOR=: test_must_fail git rebase --root --onto master &&
+	test "z$(git symbolic-ref HEAD)" = zrefs/heads/stops1
+	test 0 = $(git rev-list other...stops1 | wc -l)
+'
+
+test_done
-- 
tg: (cb706e1..) t/rr-normal (depends on: origin/master t/rebase-hook-order)

^ permalink raw reply related

* Re: [PATCH v2 1/3] rebase: learn to rebase root commit
From: Junio C Hamano @ 2009-01-02 23:07 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git
In-Reply-To: <200901022354.17922.trast@student.ethz.ch>

Thomas Rast <trast@student.ethz.ch> writes:

>> ${1+"$@"} should be equivalent to "$@" in modern Bourne shell variants
>> that are POSIX compliant.
>
> So do you want me to change it back to ${1+"$@"}?

No.  I was merely answering your question.

^ permalink raw reply

* Re: [PATCH v3 2/4] rebase: learn to rebase root commit
From: Junio C Hamano @ 2009-01-02 23:06 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, bss
In-Reply-To: <7c74d8be216b4667f470e34644c4aa26dcfe0cfb.1230935095.git.trast@student.ethz.ch>


>  # If a hook exists, give it a chance to interrupt
> -run_pre_rebase_hook ${1+"$@"}
> +run_pre_rebase_hook $root_flag $upstream_name "$@"

You'd have to quote the $upstream_name properly here, because the original
command line could well have been:

	$ git rebase 'master@{3 days ago}'

^ permalink raw reply

* Re: [PATCH 0/3] Teach Git about the patience diff algorithm
From: Linus Torvalds @ 2009-01-02 23:05 UTC (permalink / raw)
  To: Jeff King
  Cc: Johannes Schindelin, Clemens Buchacher, Adeodato Simó,
	Pierre Habouzit, davidel, Francis Galiegue, Git ML
In-Reply-To: <20090102205208.GA9273@coredump.intra.peff.net>



On Fri, 2 Jan 2009, Jeff King wrote:
> 
> Here's another interesting one: d592b315. The commit removes dashes
> from git commands in test scripts. Git says:
> 
>         echo "tag-one-line" >expect &&
> -       git-tag -l | grep "^tag-one-line" >actual &&
> +       git tag -l | grep "^tag-one-line" >actual &&
>         test_cmp expect actual &&
> -       git-tag -n0 -l | grep "^tag-one-line" >actual &&
> +       git tag -n0 -l | grep "^tag-one-line" >actual &&
>         test_cmp expect actual &&
> -       git-tag -n0 -l tag-one-line >actual &&
> +       git tag -n0 -l tag-one-line >actual &&
>         test_cmp expect actual &&
> 
> whereas patience says:
> 
>         echo "tag-one-line" >expect &&
> -       git-tag -l | grep "^tag-one-line" >actual &&
> -       test_cmp expect actual &&
> -       git-tag -n0 -l | grep "^tag-one-line" >actual &&
> -       test_cmp expect actual &&
> -       git-tag -n0 -l tag-one-line >actual &&
> +       git tag -l | grep "^tag-one-line" >actual &&
> +       test_cmp expect actual &&
> +       git tag -n0 -l | grep "^tag-one-line" >actual &&
> +       test_cmp expect actual &&
> +       git tag -n0 -l tag-one-line >actual &&
>         test_cmp expect actual &&

Yeah, the bazaar version clearly is inferior here. But again, I don't 
think that's actually a patience diff issue, I think it's because the 
bazaar diff has merged consecutive diff lines too aggressively.

I suspect both patience and the straight Mayers diff (that git uses) 
actually finds exactly the same differences, and then bazaar has a "merge 
closeby -/ pairs together if there is just a single unmodified line in 
between them". 

And _that_ is where it should care whether the unmodified line is complex 
or not. If it's complex, you shouldn't merge it into the -/+ region.

(but yes, it's possible that the bazaar diff uses "uniqueness" as a 
complexity analysis marker, and while that is somewhat valid, it is _not_ 
valid enough to be useful. Unique lines tend to be complex, but complex 
lines are _not_ always unique)

		Linus

^ permalink raw reply

* Re: how to track the history of a line in a file
From: Junio C Hamano @ 2009-01-02 22:54 UTC (permalink / raw)
  To: david; +Cc: Jeff King, git
In-Reply-To: <alpine.DEB.1.10.0901021544580.21567@asgard.lang.hm>

david@lang.hm writes:

> I was misunderstanding git blame

You may find the --porcelain output format of git-blame useful to make
your script safer and more robust.

^ permalink raw reply

* Re: [PATCH v2 1/3] rebase: learn to rebase root commit
From: Thomas Rast @ 2009-01-02 22:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzli9b9y6.fsf@gitster.siamese.dyndns.org>

[-- Attachment #1: Type: text/plain, Size: 477 bytes --]

Junio C Hamano wrote:
> Thomas Rast <trast@student.ethz.ch> writes:
> 
> > I'm still not sure what ${1+"$@"} was about by the way.
> 
> It is one of the many old-timer's portability idioms that let us work
> around bugs in some ancient shell implementations.
> 
> ${1+"$@"} should be equivalent to "$@" in modern Bourne shell variants
> that are POSIX compliant.

So do you want me to change it back to ${1+"$@"}?

-- 
Thomas Rast
trast@{inf,student}.ethz.ch


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCH rfc v2] git-sh-setup: Fix scripts whose PWD is a symlink to a work-dir on OS X
From: Marcel Koeppen @ 2009-01-02 22:53 UTC (permalink / raw)
  To: git
In-Reply-To: <1230649824-1893-1-git-send-email-marcel@oak.homeunix.org>

Hi,

Am 30.12.2008 um 16:10 schrieb Marcel M. Cary:

> I sent the first rev of this patch to just Brian.  It didn't have
> either of the unit test changes.  He said it fixed all but t2300.3,
> where cd_to_toplevel doesn't actually "cd", so I made the same change
> to the unit test itself.  Can someone with OS X try running the test
> suite with v2 of this patch?  I don't have OS X readily available.

the patch fixes t2300-cd-to-toplevel and t5521-pull-symlink for me.

	Marcel

[I don't know why my replies get lost, so I dropped all individual  
recipients on this third try...]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox