Git development
 help / color / mirror / Atom feed
* Re: [PATCH] rev-list: add "--full-objects" flag.
From: Eric W. Biederman @ 2005-07-12  0:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.58.0507110928070.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>> 
>> I guess I was expecting to pull from one tree into another unrelated
>> tree.  Getting a tree with two heads and then be able to merge them
>> together.
>
> You can do it, but you have to do it by hand. It's a valid operation, but 
> it's not an operation I want people to do by mistake, so it's not 
> something the trivial helper scripts help with.
>
> The way to do it by hand is to just use something stupid that doesn't
> understand what it's doing anyway, and just copy the files over. "cp -a" 
> or "rsync" works fine. Then just do "git resolve" by hand. It's not very 
> hard at all, but it's definitely something that should be a special case.

Ok.  Only the dumb methods are allowed.

>> A couple of questions.
>> 
>> 1) Does git-clone-script when packed copy the entire repository
>>    or just take a couple of slices of the tree where you have
>>    references?
>
> It only gets the objects needed for the references, nothing more.
>
> So if you only get one branch, it will leave the objects that are specific 
> to other branches alone.

Hmm.  As I recall reading the code it grabs everything that is
in .git/refs/*.  So I would actually expect it to grab all of the
branches.   My real question was different.  With a clone it
appears to just get the objects used to compose a tree object,
but none of the history available by looking at the commit
parents is obtained.  Not at all what I would expect for
an operation named clone.

Eric

^ permalink raw reply

* [ANNOUNCE] Cogito 0.12.1
From: Petr Baudis @ 2005-07-12  1:00 UTC (permalink / raw)
  To: git

  Hello,

  here is Cogito 0.12.1, another desperate attempt to keep pace with
'@' or Linus, the named Human Master Coder. (Linus, the Human Master
Coder, mumbles arcane do { formulae } while (0)!  Some kind of force
seems to attack your mind.  Everything suddenly looks so different...
You are confused.)  Visit the greater spellbook vault at

	http://www.kernel.org/pub/software/scm/cogito

or re-attune yourself to the git plane (in case you are already
connected to the mana flow of Cogito) for updated powerful
counter-magick.

  Most of it is upstream stuff. Otherwise, almost everything are
bugfixes and updates to deal better with the mighty pack stuff.
Important bugfixes is fixed parent-id (cg-admin-uncommit, subsequently)
and massive pull fixes w.r.t. pulling from packed repositories and
cross-filesystem local pull.

  Oh, don't get used too much to the new cg-info script's semantics,
I want to move the functionality to cg-status; I just forgot to do it
before tagging the release and only remembered it now.

  May the sun always shine on you,

-- 
			Petr "the High Elven Codethrower" Baudis
Stuff: http://pasky.or.cz/
You play too little rogue-like RPG games, apparently.

^ permalink raw reply

* Re: Trial git RPM's..
From: Eric W. Biederman @ 2005-07-12  0:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507110958400.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>
>> Are you still up for a patch that records who and when made a tag?
>> I sent one but it seems to have been lost.
>
> I'd really actually prefer for the code to be shared with the commit code, 
> so that the user info (name, email, date) would not just be exactly the 
> same, but would share the same code so that we don't end up having them 
> ever get out of sync. 

Sounds fair.

> That would imply moving parts of "git-tag-script" into mktag.c.

Actually I was looking at doing a git-ident thing that will
just compute who git thinks you are.  And then git-commit-tree can
just popen it to share code.  That looks like how the logic has
been accomplished in other places.

Moving parts of git-tag-script into mktag is hard because you
have to generate a flat file to pass to gpg.  And I don't think
I am ready to hard code the call to gpg into mktag, as some other
signing method may come along.  Although that may be the saner
choice.

Anyway the git-ident thing is easy and informative for debugging
so I will finish coding that up as soon as I get home.

Eric

^ permalink raw reply

* Re: Trial git RPM's..
From: Eric W. Biederman @ 2005-07-12  0:58 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507110958400.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>> 
>> A couple of pieces.  The dist target has assumes git-tar-tree is in the
>> path.  Making it so you have to have git installed to build the rpm.
>
> Yes. Maybe we could relax that requirement by using "./git-tar-tree" or 
> something? That still requires that you have _built_ git to do the rpm, 
> but at least you won't have had to install it.
>
> Does that fit the rpm build process? Or does an rpm build make something 
> like that really inconvenient? I don't know, patches welcome.

That would be sane.  The reason I worry about having it installed is
that if git-tar-tree changes without building first you will run
the old version instead of the new one.

>> The man pages are not built. The build dependencies do not call out
>> the tools necessary to build the man pages.
>
> Most people don't have asciidoc, and I'm not sure we want to require it. 
> Maybe we could have a separate "make man-rpm" target for that?

Or just have a make man target and only require the rpm to use it.
You certainly want to require making the man pages when building
the rpm.  Which means only those people who build rpms or build
man pages need asciidoc.  

>> And it does not pass my torture test of building rpm's on debian,
>> but that is not a huge problem.
>
> Ok, why is debian problematic? 

Mostly because debian is not rpm based.  If you are real careful
you can build rpm's on debian.   It is almost as bad as complaining
that git does not build on windows with Microsoft's compiler.  I was
getting a really generic error.  I need to look into it deeper to see
if is something that is avoidable.

> Is there some missing dependency or 
> something? I really haven't ever done an rpm, and the git rpm target was 
> all done by Chris Wright, so I don't have any clue at all. Again, patches 
> welcome.

Will do.

Eric

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  0:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Marc Singer, git
In-Reply-To: <7vll4dndwu.fsf@assigned-by-dhcp.cox.net>



On Mon, 11 Jul 2005, Junio C Hamano wrote:
> 
>  - we allow git-checkout-script with a tag; I think we store the tag
>    object without dereferencing in .git/HEAD;

No, git-checkout-script _shouldn't_ have done that. It will do the 
read-tree on the tag (which will do the right thing), but it won't change 
the HEAD itself.

But I think Marc has/had an older git-checkout-script. The original one
didn't do branches at all, and indeed just blindly wrote its result into
.git/HEAD.

> My current preference is to keep .git/refs/heads tag free.  At
> least, I do not think we should ever write non commits to
> .git/*_HEAD.

And we don't. Not any more. 

However, right now we don't update .git/HEAD at _all_ unless we checked 
out a specific branch. Part of that is that we don't really know what we 
should change. Should we reset the current branch to that tag? Should we 
switch to the "master" branch, and switch _that_ to that tag? Should we 
create a totally new branch for just this thing?

Creating a new branch ends up being the only _safe_ option, but what 
should we choose as the branch name? 

		Linus

^ permalink raw reply

* Re: [PATCH] rev-list: add "--full-objects" flag.
From: Linus Torvalds @ 2005-07-12  1:14 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: Junio C Hamano, git
In-Reply-To: <m13bqk26pp.fsf@ebiederm.dsl.xmission.com>



On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>
> Ok.  Only the dumb methods are allowed.

Well, no, you can actually do git-clone-pack by hand in that git archive,
and it will use the smart packing to get the other end, even if it is
totally unrelated to the current project.

But you have to do it by "hand" in the sense that none of the nice helper
scripts will help you to do this. Merging two unrelated projects really is
a very special operation. I've done it once (gitk into git), and I don't
think we'll see it done very many times again.

> > So if you only get one branch, it will leave the objects that are specific 
> > to other branches alone.
> 
> Hmm.  As I recall reading the code it grabs everything that is
> in .git/refs/*.

Only by default.

If you specify a branch (or five) git-clone-pack will grab only that
branch.

However, I don't think "git clone" (the script) even exposes that, so
right now you'd not even see it - "git clone" only exposes the "get all
the branches by default" behaviour.

		Linus

^ permalink raw reply

* Re: Trial git RPM's..
From: Linus Torvalds @ 2005-07-12  1:15 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: Git Mailing List
In-Reply-To: <m1vf3gzvvd.fsf@ebiederm.dsl.xmission.com>



On Mon, 11 Jul 2005, Eric W. Biederman wrote:
> 
> Actually I was looking at doing a git-ident thing that will
> just compute who git thinks you are.  And then git-commit-tree can
> just popen it to share code.  That looks like how the logic has
> been accomplished in other places.

I hate popen() if there's a reasonable functional interface in a library.

popen() is damn inefficient for doing something like this that is all C 
anyway.

		Linus

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  1:43 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Marc Singer, git
In-Reply-To: <Pine.LNX.4.58.0507111646000.17536@g5.osdl.org>



On Mon, 11 Jul 2005, Linus Torvalds wrote:
>
> No, git-checkout-script _shouldn't_ have done that. It will do the 
> read-tree on the tag (which will do the right thing), but it won't change 
> the HEAD itself.

In preparation of actually updating the HEAD, I just made "git checkout" 
verify that it only checks out a commit, not a tree tag or something like 
that. Too late for Marc, but next time around a "git checkout v2.6.11" 
will result in

	[torvalds@g5 linux]$ git checkout v2.6.11
	error: Object 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c is a tree, not a commit
	Needed a single revision

That's not exactly _obvious_ either, but hey, it's at least a half-way
readable and understandable error, and it's obviously correct to somebody
who knows how git works.

That still leaves the question about what to do when you do

	git checkout v2.6.12

which _is_ a valid operation. Right now it will "check out" that tag, in 
the sense that it will make the working tree correspond to v2.6.12, but it 
won't actually touch HEAD at all. The question is, what _should_ it do to 
head?

Should it just reset HEAD to point to .git/refs/master, and then write the
commit ID to it? That may actually sometimes be exactly what you want, and
at least it will result in a consistent state (ie the next commit will
have the right parent). On the other hand, it will blow away whatever the
old "master" branch contained, and thus likely leave an unreachable
commit.

On the other hand, creating a new branch might be a but surprising to 
people: "But I just wanted to check it out". But as far as I can see, it's 
the only safe thing to do, and it has the advantage that you can then go 
back to the old state with a simple "git checkout master".

But what about the branch name? Should we just ask the user? Together with 
a flag, like

	git checkout -b new-branch v2.6.12

for somebody who wants to specify the branch name? Or should we pick a 
random name and add a helper function to rename a branch later?

Opinions?


^ permalink raw reply

* Re: [PATCH 2/2] Demo support for packs via HTTP
From: Daniel Barkalow @ 2005-07-12  1:54 UTC (permalink / raw)
  To: Darrin Thompson; +Cc: git, Linus Torvalds, Petr Baudis
In-Reply-To: <1121118544.3939.6.camel@localhost.localdomain>

On Mon, 11 Jul 2005, Darrin Thompson wrote:

> On Sun, 2005-07-10 at 15:56 -0400, Daniel Barkalow wrote:
> > +	curl_easy_setopt(curl, CURLOPT_FILE, indexfile);
> > +	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
> > +	curl_easy_setopt(curl, CURLOPT_URL, url);
> 
> I was hoping to send in a patch which would turn on user auth and turn
> off ssl peer verification.
> 
> Your (preliminary obviously) patch puts curl handling in two places. Is
> there a place were I can safely start working on adding the needed
> setopts?

If I understand the curl documentation, you should be able to set options 
on the curl object when it has just been created, if those options aren't
going to change between requests. Note that I make requests from multiple
places, but I use the same curl object for all of them.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Marc Singer @ 2005-07-12  2:10 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.58.0507111833380.17536@g5.osdl.org>

On Mon, Jul 11, 2005 at 06:43:23PM -0700, Linus Torvalds wrote:
> 
> 
> On Mon, 11 Jul 2005, Linus Torvalds wrote:
> >
> > No, git-checkout-script _shouldn't_ have done that. It will do the 
> > read-tree on the tag (which will do the right thing), but it won't change 
> > the HEAD itself.
> 
> In preparation of actually updating the HEAD, I just made "git checkout" 
> verify that it only checks out a commit, not a tree tag or something like 
> that. Too late for Marc, but next time around a "git checkout v2.6.11" 

:-) 

> will result in
> 
> 	[torvalds@g5 linux]$ git checkout v2.6.11
> 	error: Object 5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c is a tree, not a commit
> 	Needed a single revision
> 
> On the other hand, creating a new branch might be a but surprising to 
> people: "But I just wanted to check it out". But as far as I can see, it's 
> the only safe thing to do, and it has the advantage that you can then go 
> back to the old state with a simple "git checkout master".
> 
> But what about the branch name? Should we just ask the user? Together with 
> a flag, like
> 
> 	git checkout -b new-branch v2.6.12
> 
> for somebody who wants to specify the branch name? Or should we pick a 
> random name and add a helper function to rename a branch later?
> 
> Opinions?

>From my POV, what I want is a branch with the tag v2.6.12 as the basis
of the branch.  I'm guessing that -b means "make me a branch and call
it this".

 # git checkout -b BRANCH_NAME [TAG]

If the TAG is omitted, the branch is made from the current HEAD or
some other reasonable point defined by the current working directory.

Are uncommitted changes present in the working directory maintained?
Discarded?  I wont't care since I'll never be doing that.  At least,
not on purpose.

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Junio C Hamano @ 2005-07-12  2:21 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Marc Singer, git
In-Reply-To: <Pine.LNX.4.58.0507111833380.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> But what about the branch name? Should we just ask the user? Together with 
> a flag, like
>
> 	git checkout -b new-branch v2.6.12
>
> for somebody who wants to specify the branch name? Or should we pick a 
> random name and add a helper function to rename a branch later?
>
> Opinions?

How about treating "master" a temporary thing --- "whatever I
happen to be working on right now"?

 - git branch <branch-name>       ;# copies master to branch-name;
				     if branch-name exists in refs/heads,
                                     warn and refuse.  Override
				     with --force flag.

 - git checkout <branch-name>     ;# copies branch-name to master; but
                                     if master does not match any
                                     of the other refs/heads/, warn
                                     and refuse.  Override with
                                     --force flag.

Yes I realize that you have to be careful when to push to your
public repository if you take this route, but this is only
relevant to people like Jeff with multiple heads, and I think he
publicly stated that his "refs/heads/master" aka .git/HEAD does
not mean much and what matters are his branch heads.  People who
do not use multiple branches but just checks out various tags,
the above would be reasonably convenient.

^ permalink raw reply

* Re: [PATCH] rev-list: add "--full-objects" flag.
From: Eric W. Biederman @ 2005-07-12  2:38 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.58.0507111810380.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>> > So if you only get one branch, it will leave the objects that are specific 
>> > to other branches alone.
>> 
>> Hmm.  As I recall reading the code it grabs everything that is
>> in .git/refs/*.
>
> Only by default.
>
> If you specify a branch (or five) git-clone-pack will grab only that
> branch.
>
> However, I don't think "git clone" (the script) even exposes that, so
> right now you'd not even see it - "git clone" only exposes the "get all
> the branches by default" behaviour.

Yep.

The question:
Does git-upload-pack which gets it's list of objects
with "git-rev-list --objects needed1 needed2 needed3 ^has1 ^has2 ^has3"
get any history beyond the top of tree of each branch.  

As I read the code it does not.  

If the code does not get the history I see some problems.
In particular merging with a branch is hard because we
may not pull the common history point.

Eric

^ permalink raw reply

* Re: Trial git RPM's..
From: Eric W. Biederman @ 2005-07-12  2:39 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507111815180.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>> 
>> Actually I was looking at doing a git-ident thing that will
>> just compute who git thinks you are.  And then git-commit-tree can
>> just popen it to share code.  That looks like how the logic has
>> been accomplished in other places.
>
> I hate popen() if there's a reasonable functional interface in a library.
> popen() is damn inefficient for doing something like this that is all C 
> anyway.

Ok two new files then.  The new library function, and then
the utility that calls it.

Eric

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  3:09 UTC (permalink / raw)
  To: Marc Singer; +Cc: Junio C Hamano, git
In-Reply-To: <20050712021004.GA27576@buici.com>



On Mon, 11 Jul 2005, Marc Singer wrote:
> 
> From my POV, what I want is a branch with the tag v2.6.12 as the basis
> of the branch.  I'm guessing that -b means "make me a branch and call
> it this".

Yup. That would be the interface.

>  # git checkout -b BRANCH_NAME [TAG]
> 
> If the TAG is omitted, the branch is made from the current HEAD or
> some other reasonable point defined by the current working directory.

That would be the most natural thing that would fall out of this kind of 
interface.

> Are uncommitted changes present in the working directory maintained?
> Discarded?  I wont't care since I'll never be doing that.  At least,
> not on purpose.

They'd be maintained. If they clash with the target being checked out (ie
the checked-out tag would have changes to those files) it would error out
with a "I can't do that, Dave".

Unless you give the "-f" flag, in which case they're all thrown out, and
"git checkout" will force the new state and throw away any old state
entirely.

			Linus

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  3:18 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Marc Singer, git
In-Reply-To: <7voe98g3ws.fsf@assigned-by-dhcp.cox.net>



On Mon, 11 Jul 2005, Junio C Hamano wrote:
>
> > Opinions?
> 
> How about treating "master" a temporary thing --- "whatever I
> happen to be working on right now"?

I'd not mind with this in theory, but it has the fundamental problem that 
we can end up losing sight of commits we have, and then have no way to 
reach them.

Which is ok per se - sometimes you simply don't care about them, and I
occasionally drop some commits on purpose when I've done something I
decide to undo and then do a "git prune" to get rid of the objects.

But I don't want this to happen _easily_.

Your examples aren't actually very interesting:

>  - git branch <branch-name>       ;# copies master to branch-name;
> 				     if branch-name exists in refs/heads,
>                                      warn and refuse.  Override
> 				     with --force flag.
> 
>  - git checkout <branch-name>     ;# copies branch-name to master; but
>                                      if master does not match any
>                                      of the other refs/heads/, warn
>                                      and refuse.  Override with
>                                      --force flag.

because those two examples end up avoiding the _real_ issue, which is the

	git checkout v2.6.12

case, which is exactly the case that would need a "--force" flag, since 
master is what you're working on before. And --force would drop that 
information. 

So I want something that naturally works with this (very reasonable) way 
of working, and does _not_ force people to drop information.

In your world, you'd have to first save the old master with

	git branch work-branch

and then you could do

	git checkout v2.6.12

to start on "master" anew. That's fair, but it's conceptually very wrong: 
it rquires you to name the _old_ thing, which to me just sounds very 
confusing indeed. You don't care about the old thing, it's the _new_ thing 
you care about.

So at least to me it makes much more sense to say "ok, I'll start
something new, and call it xyzzy", than "ok, I'll start something new, and
I'll save the old under 'old'".

The "old" thing might not even be anything you worked on (it might be
something you just cloned from somebody else), so you giving it a name 
isn't very logical. In contrast, you're clearly doing something active 
with the new thing, so naming _that_ makes sense.

		Linus

^ permalink raw reply

* Re: [PATCH] rev-list: add "--full-objects" flag.
From: Linus Torvalds @ 2005-07-12  3:21 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: Junio C Hamano, git
In-Reply-To: <m164vg7nqo.fsf@ebiederm.dsl.xmission.com>



On Mon, 11 Jul 2005, Eric W. Biederman wrote:
> 
> The question:
> Does git-upload-pack which gets it's list of objects
> with "git-rev-list --objects needed1 needed2 needed3 ^has1 ^has2 ^has3"
> get any history beyond the top of tree of each branch.  
> 
> As I read the code it does not.  

It does. It gets all the history necessary for each branch. git-rev-list
will walk the whole history until it hits commits that as been marked as
uninteresting (or the parents of commits that have been marked as
uninteresting), and those are the ones that the receiver already has, of
course.

So after you get a pack, you have all the history for all the branches you 
got.

A branch you _didn't_ get, you don't get any history for, of course, but 
that doesn't matter. You'll get that history if you ever pull the branch 
later.

			Linus

^ permalink raw reply

* Re: [PATCH] rev-list: add "--full-objects" flag.
From: Eric W. Biederman @ 2005-07-12  3:39 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.58.0507112018560.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Mon, 11 Jul 2005, Eric W. Biederman wrote:
>> 
>> The question:
>> Does git-upload-pack which gets it's list of objects
>> with "git-rev-list --objects needed1 needed2 needed3 ^has1 ^has2 ^has3"
>> get any history beyond the top of tree of each branch.  
>> 
>> As I read the code it does not.  
>
> It does. It gets all the history necessary for each branch. git-rev-list
> will walk the whole history until it hits commits that as been marked as
> uninteresting (or the parents of commits that have been marked as
> uninteresting), and those are the ones that the receiver already has, of
> course.

Ok.  So the intention is sane then.

Looking closer it appears that commit_list_insert is recursive
and that is what I missed.

> So after you get a pack, you have all the history for all the branches you 
> got.
>
> A branch you _didn't_ get, you don't get any history for, of course, but 
> that doesn't matter. You'll get that history if you ever pull the branch 
> later.

Right.  Things work well if you have all of the history.


Eric

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Junio C Hamano @ 2005-07-12  3:41 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Marc Singer, git
In-Reply-To: <Pine.LNX.4.58.0507112010120.17536@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> So at least to me it makes much more sense to say "ok, I'll start
> something new, and call it xyzzy", than "ok, I'll start something new, and
> I'll save the old under 'old'".
>
> The "old" thing might not even be anything you worked on (it might be
> something you just cloned from somebody else), so you giving it a name 
> isn't very logical. In contrast, you're clearly doing something active 
> with the new thing, so naming _that_ makes sense.

What I had mind was ``If you do not care about the current
"master", just say "checkout --force"''.

When I start working on something I often do not know what the
thing I am going to work on ends up to be.  So I would start
from v2.6.12 tag, do random hacking, and when I got into a
reasonable shape, I would say ``Ok, this is worth saving.  Let's
name it "foobar" branch and continue.''  And I would probably
switch to some other subproject when an urgent bugfix comes in,
and I would not want to lose my "master" _then_.  So (the
"branch" one has been revised):

  checkout [--force] <commit-ish>

   In addition to reading the tree and updating the work tree,
   stores "<commit-ish>^0" in .git/refs/heads/master.  However,
   if the current "master" is not something that matches a
   refs/*/*, then the user will be losing the trail between
   "master" before checkout and what is recorded in refs/, so
   the user needs to allow me explicitly to do it.

  branch <branch-name>

   Save the current "master" to branch-name.  If the user makes
   a mistake and tries to store the "master" head into a wrong
   branch, that would lose development trail of the branch being
   overwritten, so if the named branch exists and "master" is
   not a descendent of it, the user needs to explicitly tell me
   that it is OK to do so.

I do not quite follow your objections.  I do not think I am
forcing anybody to name an old thing.  Do you mean that "I've
been working on A and now I want to switch to B; so I'll save
the current state in A and switch to B" is too redundant, and I
should just let the user say "I've been working on something I
do not care to remember, now I want to switch to B, so just take
me to B and you should remember where I was and save it to A
automatically"?  That sort of makes sense to me.

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  3:49 UTC (permalink / raw)
  To: Marc Singer; +Cc: Junio C Hamano, Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507112005540.17536@g5.osdl.org>



On Mon, 11 Jul 2005, Linus Torvalds wrote:
> On Mon, 11 Jul 2005, Marc Singer wrote:
> > 
> > From my POV, what I want is a branch with the tag v2.6.12 as the basis
> > of the branch.  I'm guessing that -b means "make me a branch and call
> > it this".
> 
> Yup. That would be the interface.
> 
> >  # git checkout -b BRANCH_NAME [TAG]
> > 
> > If the TAG is omitted, the branch is made from the current HEAD or
> > some other reasonable point defined by the current working directory.
> 
> That would be the most natural thing that would fall out of this kind of 
> interface.

Ok, done. 

Now, if you try to do

	git checkout v2.6.12

git will complain with

	git checkout: you need to specify a new branch name

and some day (when I can get my act together and have man-pages that 
work), there would even be documentation for the "-b" flag to specify the 
branch name. And indeed, if you only specify the branch name, it will 
just create it and switch to it from the current HEAD.

So while there are no docs, the checkin comment hopefully says it all:

		Linus
---
commit 91dcdfd3b5331d955cfb60edf8930f1b5c142905
Author: Linus Torvalds <torvalds@g5.osdl.org>
Date:   Mon Jul 11 20:44:20 2005 -0700

    Make "git checkout" create new branches on demand

    In particular, if we check out something that isn't an old branch, it
    now requires a new branch-name to check the thing out into.

    So, for example:

        git checkout -b my-branch v2.6.12

    will create the new branch "my-branch", and start it at v2.6.12, while

        git checkout master

    will just switch back to the master branch.

    Of course, if you want to create a new branch "my-branch" and _not_
    check it out, you could have done so with just

        git-rev-parse v2.6.12^0 > .git/refs/heads/my-branch

    which I think I will codify as "git branch".

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  3:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Marc Singer, git
In-Reply-To: <7v8y0cg07c.fsf@assigned-by-dhcp.cox.net>



On Mon, 11 Jul 2005, Junio C Hamano wrote:
> 
> I do not quite follow your objections.  I do not think I am
> forcing anybody to name an old thing.

Sure you are. You're forcing them to make a choice, where both choices 
are bad. Either:

 - name an old thing (that you may not even have worked on - "master" from 
   a newly cloned repo)

 - throw the old master state away ("--force")

Either choice is bad.

		Linus

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Marc Singer @ 2005-07-12  3:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7v8y0cg07c.fsf@assigned-by-dhcp.cox.net>

On Mon, Jul 11, 2005 at 08:41:43PM -0700, Junio C Hamano wrote:
> When I start working on something I often do not know what the
> thing I am going to work on ends up to be.  So I would start
> from v2.6.12 tag, do random hacking, and when I got into a
> reasonable shape, I would say ``Ok, this is worth saving.  Let's
> name it "foobar" branch and continue.''  And I would probably
> switch to some other subproject when an urgent bugfix comes in,
> and I would not want to lose my "master" _then_.  So (the
> "branch" one has been revised):

Isn't that what a tag is for?

  o Make a sandbox
  o Commit cool changes
  o Tag the last commit object
  o Throw sandbox away.
  o Push changes or generate patch based on the tag

The change is that we can create a sandbox by giving it a starting
point, a tag.  If we decide we want to keep working on this branch,
all we'd have to do is go back to that tag, although I admit it may
seem sloppy to have to create a new branch from a tag'd commit that we
originally part of a branch.

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Linus Torvalds @ 2005-07-12  4:34 UTC (permalink / raw)
  To: Marc Singer; +Cc: Junio C Hamano, Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507112045420.17536@g5.osdl.org>



On Mon, 11 Jul 2005, Linus Torvalds wrote:
> 
>     Of course, if you want to create a new branch "my-branch" and _not_
>     check it out, you could have done so with just
> 
>         git-rev-parse v2.6.12^0 > .git/refs/heads/my-branch
> 
>     which I think I will codify as "git branch".

And now we have that "git branch". It's a trivial one-liner, except with
the setup and error checking it's actually more like six lines.

		Linus

---
commit 37f1a519f2ea0ce912ccd7c623aea992147c3900
Author: Linus Torvalds <torvalds@g5.osdl.org>
Date:   Mon Jul 11 21:30:23 2005 -0700

    Add "git branch" script

    You can use it as

        git branch <branchname> [start-point]

    and it creates a new branch of name <branchname>.  If a starting point
    is specified, that will be where the branch is created, otherwise it
    will be created at the current HEAD.

    The sequence

        git branch xyz abc
        git checkout xyz

    can also be written as

        git checkout -b xyz abc

    as per the previous commit.

^ permalink raw reply

* [PATCH] tagger id
From: Eric W. Biederman @ 2005-07-12  4:39 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507111815180.17536@g5.osdl.org>


This patch adds a command git-id for use on
the command line to see what git will set your id too,
and for use in scripts (git-tag-script) so they can get your git id.

The common code for computing the git-id is moved to ident.c

Fix parse_date to not mind being passed a constant date
to parse.

The code to compute the identifier has been restructured
to at least make a reasonable stab at error handling.  The
original version had so many unchecked return values it was
just scary to think about.

Eric

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ PROG=   git-update-cache git-diff-files 
 	git-diff-stages git-rev-parse git-patch-id git-pack-objects \
 	git-unpack-objects git-verify-pack git-receive-pack git-send-pack \
 	git-prune-packed git-fetch-pack git-upload-pack git-clone-pack \
-	git-show-index
+	git-show-index git-id
 
 all: $(PROG)
 
@@ -57,7 +57,7 @@ install: $(PROG) $(SCRIPTS)
 
 LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \
 	 tag.o date.o index.o diff-delta.o patch-delta.o entry.o path.o \
-	 epoch.o refs.o csum-file.o pack-check.o pkt-line.o connect.o
+	 epoch.o refs.o csum-file.o pack-check.o pkt-line.o connect.o ident.o
 LIB_FILE=libgit.a
 LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h \
 	pack.h pkt-line.h refs.h
diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -208,9 +208,14 @@ extern void *read_object_with_reference(
 					unsigned char *sha1_ret);
 
 const char *show_date(unsigned long time, int timezone);
-void parse_date(char *date, char *buf, int bufsize);
+void parse_date(const char *date, char *buf, int bufsize);
 void datestamp(char *buf, int bufsize);
 
+int git_ident(char *buf, size_t bufsize,
+	const char *env_name, const char *env_email, const char *env_date);
+int git_committer_ident(char *buf, size_t bufsize);
+int git_author_ident(char *buf, size_t bufsize);
+
 static inline void *xmalloc(size_t size)
 {
 	void *ret = malloc(size);
diff --git a/commit-tree.c b/commit-tree.c
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -5,9 +5,10 @@
  */
 #include "cache.h"
 
-#include <pwd.h>
 #include <time.h>
 #include <ctype.h>
+#include <string.h>
+#include <errno.h>
 
 #define BLOCKING (1ul << 14)
 
@@ -45,39 +46,6 @@ static void add_buffer(char **bufp, unsi
 	memcpy(buf + size, one_line, len);
 }
 
-static void remove_special(char *p)
-{
-	char c;
-	char *dst = p, *src = p;
-
-	for (;;) {
-		c = *src;
-		src++;
-		switch(c) {
-		case '\n': case '<': case '>':
-			continue;
-		}
-		*dst++ = c;
-		if (!c)
-			break;
-	}
-
-	/*
-	 * Go back, and remove crud from the end: some people
-	 * have commas etc in their gecos field
-	 */
-	dst--;
-	while (--dst >= p) {
-		unsigned char c = *dst;
-		switch (c) {
-		case ',': case ';': case '.':
-			*dst = 0;
-			continue;
-		}
-		break;
-	}
-}
-
 static void check_valid(unsigned char *sha1, const char *expect)
 {
 	void *buf;
@@ -114,16 +82,13 @@ static int new_parent(int idx)
 
 int main(int argc, char **argv)
 {
-	int i, len;
+	int i;
 	int parents = 0;
 	unsigned char tree_sha1[20];
 	unsigned char commit_sha1[20];
-	char *gecos, *realgecos, *commitgecos;
-	char *email, *commitemail, realemail[1000];
-	char date[50], realdate[50];
-	char *audate, *cmdate;
+	char committer[1000];
+	char author[1000];
 	char comment[1000];
-	struct passwd *pw;
 	char *buffer;
 	unsigned int size;
 
@@ -142,35 +107,12 @@ int main(int argc, char **argv)
 	}
 	if (!parents)
 		fprintf(stderr, "Committing initial tree %s\n", argv[1]);
-	pw = getpwuid(getuid());
-	if (!pw)
-		die("You don't exist. Go away!");
-	realgecos = pw->pw_gecos;
-	len = strlen(pw->pw_name);
-	memcpy(realemail, pw->pw_name, len);
-	realemail[len] = '@';
-	gethostname(realemail+len+1, sizeof(realemail)-len-1);
-	if (!strchr(realemail+len+1, '.')) {
-		strcat(realemail, ".");
-		getdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);
+	if (git_author_ident(author, sizeof(author)) < 0) {
+		die("Bad author! %s", strerror(errno));
+	}
+	if (git_committer_ident(committer, sizeof(committer)) < 0) {
+		die("Bad Committer! %s", strerror(errno));
 	}
-
-	datestamp(realdate, sizeof(realdate));
-	strcpy(date, realdate);
-
-	commitgecos = gitenv("GIT_COMMITTER_NAME") ? : realgecos;
-	commitemail = gitenv("GIT_COMMITTER_EMAIL") ? : realemail;
-	gecos = gitenv("GIT_AUTHOR_NAME") ? : realgecos;
-	email = gitenv("GIT_AUTHOR_EMAIL") ? : realemail;
-	audate = gitenv("GIT_AUTHOR_DATE");
-	if (audate)
-		parse_date(audate, date, sizeof(date));
-	cmdate = gitenv("GIT_COMMITTER_DATE");
-	if (cmdate)
-		parse_date(cmdate, realdate, sizeof(realdate));
-
-	remove_special(gecos); remove_special(realgecos); remove_special(commitgecos);
-	remove_special(email); remove_special(realemail); remove_special(commitemail);
 
 	init_buffer(&buffer, &size);
 	add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));
@@ -184,8 +126,8 @@ int main(int argc, char **argv)
 		add_buffer(&buffer, &size, "parent %s\n", sha1_to_hex(parent_sha1[i]));
 
 	/* Person/date information */
-	add_buffer(&buffer, &size, "author %s <%s> %s\n", gecos, email, date);
-	add_buffer(&buffer, &size, "committer %s <%s> %s\n\n", commitgecos, commitemail, realdate);
+	add_buffer(&buffer, &size, "author %s <%s> %s\n", author);
+	add_buffer(&buffer, &size, "committer %s <%s> %s\n\n", committer);
 
 	/* And add the comment */
 	while (fgets(comment, sizeof(comment), stdin) != NULL)
diff --git a/date.c b/date.c
--- a/date.c
+++ b/date.c
@@ -224,7 +224,7 @@ static int is_date(int year, int month, 
 	return 0;
 }
 
-static int match_multi_number(unsigned long num, char c, char *date, char *end, struct tm *tm)
+static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm)
 {
 	long num2, num3;
 
@@ -270,7 +270,7 @@ static int match_multi_number(unsigned l
 /*
  * We've seen a digit. Time? Year? Date? 
  */
-static int match_digit(char *date, struct tm *tm, int *offset, int *tm_gmt)
+static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt)
 {
 	int n;
 	char *end;
@@ -361,7 +361,7 @@ static int match_digit(char *date, struc
 	return n;
 }
 
-static int match_tz(char *date, int *offp)
+static int match_tz(const char *date, int *offp)
 {
 	char *end;
 	int offset = strtoul(date+1, &end, 10);
@@ -388,7 +388,7 @@ static int match_tz(char *date, int *off
 
 /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
    (i.e. English) day/month names, and it doesn't work correctly with %z. */
-void parse_date(char *date, char *result, int maxlen)
+void parse_date(const char *date, char *result, int maxlen)
 {
 	struct tm tm;
 	int offset, sign, tm_gmt;
diff --git a/git-tag-script b/git-tag-script
--- a/git-tag-script
+++ b/git-tag-script
@@ -7,6 +7,7 @@ name="$1"
 
 object=${2:-$(cat "$GIT_DIR"/HEAD)}
 type=$(git-cat-file -t $object) || exit 1
+tagger=$(git-id) || exit 1
 
 ( echo "#"
   echo "# Write a tag message"
@@ -17,8 +18,9 @@ grep -v '^#' < .editmsg | git-stripspace
 
 [ -s .tagmsg ] || exit
 
-( echo -e "object $object\ntype $type\ntag $name\n"; cat .tagmsg ) > .tmp-tag
+( echo -e "object $object\ntype $type\ntag $name\ntagger $tagger\n"; cat .tagmsg ) > .tmp-tag
 rm -f .tmp-tag.asc .tagmsg
 gpg -bsa .tmp-tag && cat .tmp-tag.asc >> .tmp-tag
+mkdir -p "$GIT_DIR/refs/tags"
 git-mktag < .tmp-tag > "$GIT_DIR/refs/tags/$name"
 #rm .tmp-tag .tmp-tag.sig
diff --git a/id.c b/id.c
new file mode 100644
--- /dev/null
+++ b/id.c
@@ -0,0 +1,36 @@
+#include "cache.h"
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+static char *id_usage = "git-id [--author | --committer]";
+
+int main(int argc, char **argv)
+{
+	char buf[1000];
+	int (*ident)(char *buf, size_t bufsize);
+	int i;
+
+	ident = git_committer_ident;
+	for(i = 1; i < argc; i++) {
+		char *arg = argv[i];
+		if (strcmp(arg, "--author") == 0) {
+			ident = git_author_ident;
+		}
+		else if (strcmp(arg, "--committer") == 0) {
+			ident = git_committer_ident;
+		}
+		else {
+			usage(id_usage);
+		}
+	}
+
+
+	if (ident(buf, sizeof(buf)) < 0) {
+		die("Cannot resolve ident: %s\n", strerror(errno));
+	}
+
+	printf("%s\n", buf);
+
+	return 0;
+}
diff --git a/ident.c b/ident.c
new file mode 100644
--- /dev/null
+++ b/ident.c
@@ -0,0 +1,144 @@
+/*
+ * GIT - The information manager from hell
+ *
+ * Copyright (C) Eric Biederman, 2005
+ */
+#include "cache.h"
+
+#include <pwd.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#define MAX_NAME 1000
+#define MAX_EMAIL 1000
+#define MAX_DATE 50
+static void remove_special(char *p)
+{
+	char c;
+	char *dst = p, *src = p;
+
+	for (;;) {
+		c = *src;
+		src++;
+		switch(c) {
+		case '\n': case '<': case '>':
+			continue;
+		}
+		*dst++ = c;
+		if (!c)
+			break;
+	}
+
+	/*
+	 * Go back, and remove crud from the end: some people
+	 * have commas etc in their gecos field
+	 */
+	dst--;
+	while (--dst >= p) {
+		unsigned char c = *dst;
+		switch (c) {
+		case ',': case ';': case '.':
+			*dst = 0;
+			continue;
+		}
+		break;
+	}
+}
+
+int git_ident(char *buf, size_t bufsize,
+	const char *env_name, const char *env_email, const char *env_date)
+{
+	int len;
+	char name[MAX_NAME];
+	char email[MAX_EMAIL];
+	char date[MAX_DATE];
+	struct passwd *pw;
+	int count;
+	
+	/* Lookup the user in the password file */
+	pw = getpwuid(getuid());
+	if (!pw)
+		return -1;
+
+	/* Get the users full name */
+	strncpy(name, pw->pw_gecos, sizeof(name));
+	name[sizeof(name) - 1] = '\0';
+
+	/* Get the email address with error handling */
+	len = strlen(pw->pw_name);
+	if (len >= (sizeof(email) - 2)) {
+		/* Bad user name length */
+		errno = ENOMEM;
+		return -1;
+	}
+	memcpy(email, pw->pw_name, len);
+	email[len] = '@';
+	email[len + 1] = '\0';
+
+	if (gethostname(email+len+1, sizeof(email)-len-1) < 0) {
+		return -1;
+	}
+	email[sizeof(email) - 1] = '\0';
+	len = strlen(email);
+	if (!strchr(email+len+1, '.')) {
+		if (len >= (sizeof(email) - 1)) {
+			errno = ENOMEM;
+			return -1;
+		}
+		email[len] = '.';
+		if (getdomainname(email+len+1, sizeof(email) - len - 1) < 0) {
+			return -1;
+		}
+	}
+	/* Get the date */
+	datestamp(date, sizeof(date));
+
+	if (env_name) {
+		strncpy(name, env_name, sizeof(name));
+		name[sizeof(name) - 1] = '\0';
+	}
+	if (env_email) {
+		strncpy(email, env_email, sizeof(email));
+		email[sizeof(email) - 1] = '\0';
+	}
+	if (env_date) {
+		parse_date(env_date, date, sizeof(date));
+	}
+	remove_special(name);
+	remove_special(email);
+	count = snprintf(buf, bufsize, "%s <%s> %s", name, email, date);
+	if (count > bufsize) {
+		errno = ENOMEM;
+		return -1;
+	}
+	if (count < 0) {
+		return -1;
+	}
+	return 0;
+}
+
+int git_committer_ident(char *buf, size_t bufsize)
+{
+	const char *name;
+	const char *email;
+	const char *date;
+	name  = gitenv("GIT_COMMITTER_NAME");
+	email = gitenv("GIT_COMMITTER_EMAIL");
+	date  = gitenv("GIT_COMMITTER_DATE");
+	return git_ident(buf, bufsize, name, email, date);
+}
+
+int git_author_ident(char *buf, size_t bufsize)
+{
+	const char *name;
+	const char *email;
+	const char *date;
+	name  = gitenv("GIT_AUTHOR_NAME");
+	email = gitenv("GIT_AUTHOR_EMAIL");
+	date  = gitenv("GIT_AUTHOR_DATE");
+	return git_ident(buf, bufsize, name, email, date);
+}
+
diff --git a/mktag.c b/mktag.c
--- a/mktag.c
+++ b/mktag.c
@@ -42,7 +42,7 @@ static int verify_tag(char *buffer, unsi
 	int typelen;
 	char type[20];
 	unsigned char sha1[20];
-	const char *object, *type_line, *tag_line;
+	const char *object, *type_line, *tag_line, *tagger_line;
 
 	if (size < 64 || size > MAXSIZE-1)
 		return -1;
@@ -92,6 +92,12 @@ static int verify_tag(char *buffer, unsi
 		return -1;
 	}
 
+	/* Verify the tagger line */
+	tagger_line = tag_line;
+	
+	if (memcmp(tagger_line, "tagger", 6) || (tagger_line[6] == '\n'))
+		return -1;
+
 	/* The actual stuff afterwards we don't care about.. */
 	return 0;
 }
@@ -119,7 +125,7 @@ int main(int argc, char **argv)
 		size += ret;
 	}
 
-	// Verify it for some basic sanity: it needs to start with "object <sha1>\ntype "
+	// Verify it for some basic sanity: it needs to start with "object <sha1>\ntype\ntagger "
 	if (verify_tag(buffer, size) < 0)
 		die("invalid tag signature file");
 

^ permalink raw reply

* Re: Bootstrapping into git, commit gripes at me
From: Marc Singer @ 2005-07-12  4:43 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0507112132170.17536@g5.osdl.org>

On Mon, Jul 11, 2005 at 09:34:33PM -0700, Linus Torvalds wrote:
> 
> 
> On Mon, 11 Jul 2005, Linus Torvalds wrote:
> > 
> >     Of course, if you want to create a new branch "my-branch" and _not_
> >     check it out, you could have done so with just
> > 
> >         git-rev-parse v2.6.12^0 > .git/refs/heads/my-branch
> > 
> >     which I think I will codify as "git branch".
> 
> And now we have that "git branch". It's a trivial one-liner, except with
> the setup and error checking it's actually more like six lines.

Does it make sense to think about this branch as an flow of commits?
Or is it just a starting point for a line of development?  If I make a
branch, check it out, commit changes to it, and then clobber the
working directory, can I later resume that branch of development
without creating a new branch?  Do I need to set a tag to mark the
last commit on that branch?

^ permalink raw reply

* Re: [PATCH] rev-list: add "--full-objects" flag.
From: Linus Torvalds @ 2005-07-12  4:48 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: Junio C Hamano, git
In-Reply-To: <m1wtnw66cc.fsf@ebiederm.dsl.xmission.com>



On Mon, 11 Jul 2005, Eric W. Biederman wrote:
> 
> Looking closer it appears that commit_list_insert is recursive
> and that is what I missed.

Actually, it's "pop_most_recent_commit()" that ends up being the
"recursive" part: it will pop the top-most entry, but as it is popping it 
it will push the parents of that entry onto the same list.

So basically, you can get a list of all history by first inserting the top 
entry, and then doing "pop_most_recent_commit()" until the list is empty.

Now, git-rev-list ends up being slightly more complex than that, since it
has support for multiple starting points, and marking commits (and thus
their parents) uninteresting, and two other sorting methods in addition to 
the default "by date" thing.

And then there's all the issues about tags, trees and blobs, and their
visibility as a function of the commits that are visible and the command
line arguments..

In fact, it turns out that git-rev-list is really the real heart of "git".  
Almost everything else revolves around it. Once you grok git-rev-list, you
probably really grok git.

			Linus

^ 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