threads / discuss / 43169

Re: git-show --stat on first commit

Subject: Re: git-show --stat on first commit

## tl;dr

35 messages between Nov 21, 2006 and Nov 24, 2006.

replies: 34people: 10as markdown or json

Andy Parkins· Nov 21, 2006, 13:41 UTC · lore

git-show --stat on first commit

Hello,

I'm sure this one will be known about already. git-show --stat on the the first commit doesn't show anything. I assume it's because git-diff-tree has nothing to diff against (although shouldn't that be an everything-new diff?).

Given the above; does anyone have a suggestion for what I could use as a replacement? Even just a list of the new files would be useful.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
Jakub Narebski· Nov 21, 2006, 14:01 UTC · re: Andy Parkins · lore
Andy Parkins wrote:
> I'm sure this one will be known about already.  git-show --stat on the the 
> first commit doesn't show anything.  I assume it's because git-diff-tree has 
> nothing to diff against (although shouldn't that be an everything-new diff?).
Yes, and git-diff-tree requires --root option if you want to generate
creation diff for initial (parentless, root) commit.
 
> Given the above; does anyone have a suggestion for what I could use as a 
> replacement?  Even just a list of the new files would be useful.
git show --stat --root
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Santi Béjar· Nov 21, 2006, 14:09 UTC · re: Andy Parkins · lore
On 11/21/06, Andy Parkins <andyparkins@gmail.com> wrote:
Show 8 quoted lines
> Hello,
>
> I'm sure this one will be known about already.  git-show --stat on the the
> first commit doesn't show anything.  I assume it's because git-diff-tree has
> nothing to diff against (although shouldn't that be an everything-new diff?).
>
> Given the above; does anyone have a suggestion for what I could use as a
> replacement?  Even just a list of the new files would be useful.
$ git show --stat --root

In general the initial commit diff (or stat) is hidden, but perhaps it make sense to show it in "git show", you asked fo this specifically.

Peter Baumann· Nov 21, 2006, 16:08 UTC · re: Santi Béjar · lore
On 2006-11-21, Santi Béjar <sbejar@gmail.com> wrote:
Show 16 quoted lines
> On 11/21/06, Andy Parkins <andyparkins@gmail.com> wrote:
>> Hello,
>>
>> I'm sure this one will be known about already.  git-show --stat on the the
>> first commit doesn't show anything.  I assume it's because git-diff-tree has
>> nothing to diff against (although shouldn't that be an everything-new diff?).
>>
>> Given the above; does anyone have a suggestion for what I could use as a
>> replacement?  Even just a list of the new files would be useful.
>
> $ git show --stat --root
>
> In general the initial commit diff (or stat) is hidden, but perhaps it
> make sense to show it in "git show", you asked fo this specifically.
>
> Santi

Why not make --root the default? I also stumbled over this behaviour and even asked on this list.

In my opinion this will help new users which are supprised that they can't get the diff of the inital commit (which is totaly non-intuitiv behavior).

And one less "wart" to clean, which another thread is all about. :-)
Peter
Jakub Narebski· Nov 21, 2006, 16:18 UTC · re: Peter Baumann · lore
Peter Baumann wrote:
Show 10 quoted lines
> On 2006-11-21, Santi Béjar <sbejar@gmail.com> wrote:
>> On 11/21/06, Andy Parkins <andyparkins@gmail.com> wrote:
>>> Hello,
>>>
>>> I'm sure this one will be known about already.  git-show --stat on the the
>>> first commit doesn't show anything.  I assume it's because git-diff-tree has
>>> nothing to diff against (although shouldn't that be an everything-new diff?).
>>>
>>> Given the above; does anyone have a suggestion for what I could use as a
>>> replacement?  Even just a list of the new files would be useful.
You can always use git-ls-tree
Show 12 quoted lines
>> $ git show --stat --root
>>
>> In general the initial commit diff (or stat) is hidden, but perhaps it
>> make sense to show it in "git show", you asked fo this specifically.
> 
> Why not make --root the default? I also stumbled over this behaviour and
> even asked on this list.
> 
> In my opinion this will help new users which are supprised that they
> can't get the diff of the inital commit (which is totaly non-intuitiv behavior).
> 
> And one less "wart" to clean, which another thread is all about. :-)

Because for projects imported into git first commit diff is huge, and not very interesting. By the way, git show by default doesn't show diff for merges (you need --cc for that), nor rename detection (you need -M for that).

But you can always set default diff-tree options, including --root, --cc and -M in the show.difftree configuration variable (either in repo config, or in user config). It is IMHO better solution than changing defaults.

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Peter Baumann· Nov 21, 2006, 17:16 UTC · re: Jakub Narebski · lore
On 2006-11-21, Jakub Narebski <jnareb@gmail.com> wrote:
Show 36 quoted lines
> Peter Baumann wrote:
>
>> On 2006-11-21, Santi Béjar <sbejar@gmail.com> wrote:
>>> On 11/21/06, Andy Parkins <andyparkins@gmail.com> wrote:
>>>> Hello,
>>>>
>>>> I'm sure this one will be known about already.  git-show --stat on the the
>>>> first commit doesn't show anything.  I assume it's because git-diff-tree has
>>>> nothing to diff against (although shouldn't that be an everything-new diff?).
>>>>
>>>> Given the above; does anyone have a suggestion for what I could use as a
>>>> replacement?  Even just a list of the new files would be useful.
>
> You can always use git-ls-tree
>
>>> $ git show --stat --root
>>>
>>> In general the initial commit diff (or stat) is hidden, but perhaps it
>>> make sense to show it in "git show", you asked fo this specifically.
>> 
>> Why not make --root the default? I also stumbled over this behaviour and
>> even asked on this list.
>> 
>> In my opinion this will help new users which are supprised that they
>> can't get the diff of the inital commit (which is totaly non-intuitiv behavior).
>> 
>> And one less "wart" to clean, which another thread is all about. :-)
>
> Because for projects imported into git first commit diff is huge,
> and not very interesting. By the way, git show by default doesn't show
> diff for merges (you need --cc for that), nor rename detection (you need
> -M for that).
>
> But you can always set default diff-tree options, including --root, --cc
> and -M in the show.difftree configuration variable (either in repo config,
> or in user config). It is IMHO better solution than changing defaults.
Ah. I wasn't aware of this. Thank for this nice tip.
Peter
Linus Torvalds· Nov 21, 2006, 16:31 UTC · re: Peter Baumann · lore
On Tue, 21 Nov 2006, Peter Baumann wrote:
> 
> Why not make --root the default? I also stumbled over this behaviour and
> even asked on this list.

I suspect we should make the thing a config option, and default it to "on".

I personally do _not_ want to see the root commit, because for the kernel, it's a honking huge import that does not make sense as a "diff". It's not really a diff against anything, after all - it's an import.

That's really the reason why git defaults to not showing the root diff at all: exactly because for the kernel, the initial commit was state that "just came to be", and I found it both illogical and annoying to see it as a diff, since that commit really was a "black hole" where previous history just disappeared.

But if you have the _full_ history with a new project, "--root" by default probably makes tons of sense.

> And one less "wart" to clean, which another thread is all about. :-)

I really don't think it's a wart - see above - but it depends on the project.

There's also another reason for the root being special, which is purely git-internal: the root really has no parents at all, and the normal "git diff" is "diff against parents". So from a purely implementation standpoint, the "root" case is actually a special case, and for a while I was kind of wondering whether I should do what a lot of other SCM's seem to do, namely start out with an "empty root" when doing "git init-db".

git didn't end up doing that (and I'm personally pretty happy about it), but it was one of the things I was kind of thinking about: a "git import" kind of thing would have created an initial commit which was pre-populated with the thing to import, and a "git init-db" would have created an initial root commit that was empty.

That would have made the current "don't show the root diff" behaviour very natural (and you'd still have gotten the initial diff for a new project), but on the other hand, it would have had that annoying unnecessary "init" commit, and you'd _still_ have wanted to have something like "--root" in order to show the import commit as a patch (which you _sometimes_ want to do).

So having a config option would solve the problem, but what annoys me right now about the config options is that we really should have a graphical front-end to setting those things or something, because while _I_ don't have any issues with editing a ".git/config" file, I think we're getting to the point where a lot of our problems are really about "you can do it, but you have to know a lot about git to even know you can do it".

Shawn Pearce· Nov 21, 2006, 16:47 UTC · re: Linus Torvalds · lore
Linus Torvalds <torvalds@osdl.org> wrote:
Show 6 quoted lines
> So having a config option would solve the problem, but what annoys me 
> right now about the config options is that we really should have a 
> graphical front-end to setting those things or something, because while 
> _I_ don't have any issues with editing a ".git/config" file, I think we're 
> getting to the point where a lot of our problems are really about "you can 
> do it, but you have to know a lot about git to even know you can do it".

Funny; I recently thought about rewriting Documentation/config.txt into a format that was not only easily read by asciidoc but which also had enough annotation data to render a Tk based UI from.

That way we could always have the configuration option editor match the current set of configuration options, and also offer good help for them. E.g. use a checkbox for booleans, a tk_optionMenu for choice lists, and offer up the asciidoc text as "help" on the option.

Its sort of in the back of my mind as something I'd like to do in git-gui, but right now branch management (creating, deleting, merging) is more important.

Right now git-gui does have a GUI editor for its own configuration data that it keeps in "gui" sections of .git/config and ~/.gitconfig, and lets the user view and edit both.

Peter Baumann· Nov 21, 2006, 17:11 UTC · re: Linus Torvalds · lore
On 2006-11-21, Linus Torvalds <torvalds@osdl.org> wrote:
Show 10 quoted lines
>
>
> On Tue, 21 Nov 2006, Peter Baumann wrote:
>> 
>> Why not make --root the default? I also stumbled over this behaviour and
>> even asked on this list.
>
> I suspect we should make the thing a config option, and default it to 
> "on".
>
That would be great.
Show 13 quoted lines
> I personally do _not_ want to see the root commit, because for the kernel, 
> it's a honking huge import that does not make sense as a "diff". It's not 
> really a diff against anything, after all - it's an import.
>
> That's really the reason why git defaults to not showing the root diff at 
> all: exactly because for the kernel, the initial commit was state that 
> "just came to be", and I found it both illogical and annoying to see it as 
> a diff, since that commit really was a "black hole" where previous history 
> just disappeared.
>
> But if you have the _full_ history with a new project, "--root" by default 
> probably makes tons of sense.
>
I am aware of the import problem, especially from the kernel history.

And I think handling this behaviour as a config option is the right thing, because most of the time if someone imports a project into git he will import the whole history, especially if he is using one of the cvs/svn importers. A "halfway import" as seen in the kernel repo is a special case and it is unlikely seen again.

Peter
Linus Torvalds· Nov 21, 2006, 17:20 UTC · re: Peter Baumann · lore
On Tue, 21 Nov 2006, Peter Baumann wrote:
Show 6 quoted lines
> 
> And I think handling this behaviour as a config option is the right thing,
> because most of the time if someone imports a project into git he
> will import the whole history, especially if he is using one of the
> cvs/svn importers. A "halfway import" as seen in the kernel repo is a
> special case and it is unlikely seen again.
Actually, I see "halfway imports" all the time.

I've found that some of the git things like "git grep" etc are _so_ convenient, that whenever I get a source tar-ball for _anything_, I tend to do

	zcat < xyz-123.tar.gz | tar xvf -
	cd xyz-123
	git init-db
	git add
	git commit -m "Import xyz-123"

the first thing I do. Even if I never end up changing anything in that archive, it's just that convenient (and fast - sure, doing the hashing and compression means that the "git add" might not be truly instantaneous, but it's definitely fast enough that for almost all projects, doing this is so cheap that you don't need to care).

And _especially_ for things like this, being able to do "git log -p" to check the small trivial one-liners that I might do is nice (it happens - my pine4.64 import these days has three small commits to add buildnotes and handle UTF-8 input etc).

And again, that's when you do _not_ want to see "--root". Because it's never what you actually care about.

So I think imports are important. They may be throw-away trees like mine, but they're still useful.

Olivier Galibert· Nov 21, 2006, 18:38 UTC · re: Peter Baumann · lore
On Tue, Nov 21, 2006 at 06:11:19PM +0100, Peter Baumann wrote:
Show 5 quoted lines
> And I think handling this behaviour as a config option is the right thing,
> because most of the time if someone imports a project into git he
> will import the whole history, especially if he is using one of the
> cvs/svn importers. A "halfway import" as seen in the kernel repo is a
> special case and it is unlikely seen again.

Not all projects run on a public VCS. Hell, not all projects run on a VCS at all. And in the CVS case, you don't always have enough access to actually download the repository, which afaik is needed for importing.

  OG.
Shawn Pearce· Nov 21, 2006, 18:42 UTC · re: Olivier Galibert · lore
Olivier Galibert <galibert@pobox.com> wrote:
Show 11 quoted lines
> On Tue, Nov 21, 2006 at 06:11:19PM +0100, Peter Baumann wrote:
> > And I think handling this behaviour as a config option is the right thing,
> > because most of the time if someone imports a project into git he
> > will import the whole history, especially if he is using one of the
> > cvs/svn importers. A "halfway import" as seen in the kernel repo is a
> > special case and it is unlikely seen again.
> 
> Not all projects run on a public VCS.  Hell, not all projects run on a
> VCS at all.  And in the CVS case, you don't always have enough access
> to actually download the repository, which afaik is needed for
> importing.

There is a tool floating around the 'net that will download a CVS repository and recreate the ,v files locally for you. cvssuck appears to be its name:

  http://freshmeat.net/projects/cvssuck/
Petr Baudis· Nov 21, 2006, 19:05 UTC · re: Olivier Galibert · lore
On Tue, Nov 21, 2006 at 07:38:53PM CET, Olivier Galibert wrote:
Show 11 quoted lines
> On Tue, Nov 21, 2006 at 06:11:19PM +0100, Peter Baumann wrote:
> > And I think handling this behaviour as a config option is the right thing,
> > because most of the time if someone imports a project into git he
> > will import the whole history, especially if he is using one of the
> > cvs/svn importers. A "halfway import" as seen in the kernel repo is a
> > special case and it is unlikely seen again.
> 
> Not all projects run on a public VCS.  Hell, not all projects run on a
> VCS at all.  And in the CVS case, you don't always have enough access
> to actually download the repository, which afaik is needed for
> importing.

It isn't needed. It's probably much slower over the net but that's how I created the glibc-cvs.git repository (at repo.or.cz); cvsps can operate over the network.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
The meaning of Stonehenge in Traflamadorian, when viewed from above, is:
"Replacement part being rushed with all possible speed."
Petr Baudis· Nov 21, 2006, 18:06 UTC · re: Linus Torvalds · lore
On Tue, Nov 21, 2006 at 05:31:30PM CET, Linus Torvalds wrote:
Show 12 quoted lines
> git didn't end up doing that (and I'm personally pretty happy about it), 
> but it was one of the things I was kind of thinking about: a "git import" 
> kind of thing would have created an initial commit which was pre-populated 
> with the thing to import, and a "git init-db" would have created an 
> initial root commit that was empty.
> 
> That would have made the current "don't show the root diff" behaviour very 
> natural (and you'd still have gotten the initial diff for a new project), 
> but on the other hand, it would have had that annoying unnecessary "init" 
> commit, and you'd _still_ have wanted to have something like "--root" in 
> order to show the import commit as a patch (which you _sometimes_ want to 
> do).

It's being asked by users time by time (first in April last year ;) and I'm not sure about any good answer I should tell them, so is the reason for not doing the implicit empty commit that it would be "annoying" I suppose in the log output?

Is that a reason good enough?

It would solve some of these annoying corner cases nicely, and you can still hide this empty commit from log output etc.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
The meaning of Stonehenge in Traflamadorian, when viewed from above, is:
"Replacement part being rushed with all possible speed."
Jakub Narebski· Nov 21, 2006, 18:16 UTC · re: Petr Baudis · lore
Petr Baudis wrote:
Show 18 quoted lines
> On Tue, Nov 21, 2006 at 05:31:30PM CET, Linus Torvalds wrote:
>> git didn't end up doing that (and I'm personally pretty happy about it), 
>> but it was one of the things I was kind of thinking about: a "git import" 
>> kind of thing would have created an initial commit which was pre-populated 
>> with the thing to import, and a "git init-db" would have created an 
>> initial root commit that was empty.
>> 
>> That would have made the current "don't show the root diff" behaviour very 
>> natural (and you'd still have gotten the initial diff for a new project), 
>> but on the other hand, it would have had that annoying unnecessary "init" 
>> commit, and you'd _still_ have wanted to have something like "--root" in 
>> order to show the import commit as a patch (which you _sometimes_ want to 
>> do).
> 
> It's being asked by users time by time (first in April last year ;) and
> I'm not sure about any good answer I should tell them, so is the reason
> for not doing the implicit empty commit that it would be "annoying" I
> suppose in the log output?

git repo-config show.difftree --root git repo-config whatchanged.difftree --root

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Petr Baudis· Nov 21, 2006, 18:21 UTC · re: Jakub Narebski · lore
On Tue, Nov 21, 2006 at 07:16:44PM CET, Jakub Narebski wrote:
Show 23 quoted lines
> Petr Baudis wrote:
> 
> > On Tue, Nov 21, 2006 at 05:31:30PM CET, Linus Torvalds wrote:
> >> git didn't end up doing that (and I'm personally pretty happy about it), 
> >> but it was one of the things I was kind of thinking about: a "git import" 
> >> kind of thing would have created an initial commit which was pre-populated 
> >> with the thing to import, and a "git init-db" would have created an 
> >> initial root commit that was empty.
> >> 
> >> That would have made the current "don't show the root diff" behaviour very 
> >> natural (and you'd still have gotten the initial diff for a new project), 
> >> but on the other hand, it would have had that annoying unnecessary "init" 
> >> commit, and you'd _still_ have wanted to have something like "--root" in 
> >> order to show the import commit as a patch (which you _sometimes_ want to 
> >> do).
> > 
> > It's being asked by users time by time (first in April last year ;) and
> > I'm not sure about any good answer I should tell them, so is the reason
> > for not doing the implicit empty commit that it would be "annoying" I
> > suppose in the log output?
> 
> git repo-config show.difftree --root
> git repo-config whatchanged.difftree --root

That means extra pointless setup and is besides the point anyway, I was asking about empty commits, not default command settings.

BTW, the other frequent reason why empty commits come up so frequently is a FAQ "how do I create an unrelated branch in my repository" - their idea is that they will create a new branch starting with an empty commit (of course noone would think of anything like that in inferior VCSes because replacing the checked out trees would took forever; how cool Git is!).

(The answer is usually "create the branch in a separate repo and then fetch it to the original one". But it feels a bit kludgy given the otherwise seamless support for unrelated branches. (Not that I ever was a big fan of unrelated long-lived branches in general.))

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
The meaning of Stonehenge in Traflamadorian, when viewed from above, is:
"Replacement part being rushed with all possible speed."
Shawn Pearce· Nov 21, 2006, 18:34 UTC · re: Petr Baudis · lore
Petr Baudis <pasky@suse.cz> wrote:
Show 11 quoted lines
> BTW, the other frequent reason why empty commits come up so frequently
> is a FAQ "how do I create an unrelated branch in my repository" - their
> idea is that they will create a new branch starting with an empty commit
> (of course noone would think of anything like that in inferior VCSes
> because replacing the checked out trees would took forever; how cool Git
> is!).
> 
> (The answer is usually "create the branch in a separate repo and then
> fetch it to the original one". But it feels a bit kludgy given the
> otherwise seamless support for unrelated branches. (Not that I ever was
> a big fan of unrelated long-lived branches in general.))
Or just abuse git-symbolic-ref:
	rm .git/index
	git symbolic-ref HEAD refs/heads/unrelated-branch
	git add ...
	git commit ...

see, so simple. And no need to create an unrelated repository and pull across to this one...

Andy Parkins· Nov 21, 2006, 18:39 UTC · re: Petr Baudis · lore
On Tuesday 2006, November 21 18:21, Petr Baudis wrote:
> (The answer is usually "create the branch in a separate repo and then
> fetch it to the original one". But it feels a bit kludgy given the
> otherwise seamless support for unrelated branches. (Not that I ever was
> a big fan of unrelated long-lived branches in general.))

Just as kludgy, but I did this today by writing the name of the new branch in .git/HEAD then doing

for file in $(git-ls-files); do git-update-index --force-remove $file; done
Before creating the new files and "git-commit"ing.
Andy
-- 
Dr Andrew Parkins, M Eng (Hons), AMIEE
Petr Baudis· Nov 21, 2006, 18:48 UTC · re: Andy Parkins · lore
On Tue, Nov 21, 2006 at 07:39:56PM CET, Andy Parkins wrote:
Show 13 quoted lines
> On Tuesday 2006, November 21 18:21, Petr Baudis wrote:
> 
> > (The answer is usually "create the branch in a separate repo and then
> > fetch it to the original one". But it feels a bit kludgy given the
> > otherwise seamless support for unrelated branches. (Not that I ever was
> > a big fan of unrelated long-lived branches in general.))
> 
> Just as kludgy, but I did this today by writing the name of the new branch 
> in .git/HEAD then doing
> 
> for file in $(git-ls-files); do git-update-index --force-remove $file; done
> 
> Before creating the new files and "git-commit"ing.

Ok, this approach looks actually reasonable (contrary to the frequently suggested rm approach, which is rather dangerous).

Perhaps git checkout --empty could do this?
-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
The meaning of Stonehenge in Traflamadorian, when viewed from above, is:
"Replacement part being rushed with all possible speed."
Shawn Pearce· Nov 21, 2006, 18:52 UTC · re: Petr Baudis · lore
Petr Baudis <pasky@suse.cz> wrote:
Show 9 quoted lines
> On Tue, Nov 21, 2006 at 07:39:56PM CET, Andy Parkins wrote:
> > for file in $(git-ls-files); do git-update-index --force-remove $file; done
> > 
> > Before creating the new files and "git-commit"ing.
> 
> Ok, this approach looks actually reasonable (contrary to the frequently
> suggested rm approach, which is rather dangerous).
> 
> Perhaps git checkout --empty could do this?
Or perhaps just delete .git/index?

Any git-update-index --add or git-add command will immediately create an empty index. Indeed this is the initial state after git-init-db, since there is no HEAD to load into the index there is no index...

Petr Baudis· Nov 21, 2006, 19:04 UTC · re: Shawn Pearce · lore
On Tue, Nov 21, 2006 at 07:52:59PM CET, Shawn Pearce wrote:
Show 16 quoted lines
> Petr Baudis <pasky@suse.cz> wrote:
> > On Tue, Nov 21, 2006 at 07:39:56PM CET, Andy Parkins wrote:
> > > for file in $(git-ls-files); do git-update-index --force-remove $file; done
> > > 
> > > Before creating the new files and "git-commit"ing.
> > 
> > Ok, this approach looks actually reasonable (contrary to the frequently
> > suggested rm approach, which is rather dangerous).
> > 
> > Perhaps git checkout --empty could do this?
> 
> Or perhaps just delete .git/index?
> 
> Any git-update-index --add or git-add command will immediately create
> an empty index.  Indeed this is the initial state after git-init-db,
> since there is no HEAD to load into the index there is no index...
But your working tree has still the contents of the old branch.

Sure, you could possibly just remove the files and then the index at once but that are just details.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
The meaning of Stonehenge in Traflamadorian, when viewed from above, is:
"Replacement part being rushed with all possible speed."
Junio C Hamano· Nov 21, 2006, 19:31 UTC · re: Petr Baudis · lore
Petr Baudis <pasky@suse.cz> writes:
Show 7 quoted lines
> On Tue, Nov 21, 2006 at 07:16:44PM CET, Jakub Narebski wrote:
>..
>> git repo-config show.difftree --root
>> git repo-config whatchanged.difftree --root
>
> That means extra pointless setup and is besides the point anyway, I was
> asking about empty commits, not default command settings.
I agree with you.  Personally, I think:
 - show is where the user is asking for _that_ particular
   commit, so it can safely default to --root, always.  No
   option is needed.
 - what we want for log and underlying rev-list is majorly
   dependent of the nature of the root commit.  Per repository
   (or even per root) option which defaults to "on" (I was
   going to say "off" to be backward compatible and convenient
   for "me", but even Linus says "on" so I am playing along)
   would make sense.

So just "core.showroot = yes | no" would be the only thing we would need, I think. Unless we do fancier "core.hideroot = SHA1-1 SHA1-2 ..." to say "these root should not be shown", that is.

Show 6 quoted lines
> BTW, the other frequent reason why empty commits come up so frequently
> is a FAQ "how do I create an unrelated branch in my repository" - their
> idea is that they will create a new branch starting with an empty commit
> (of course noone would think of anything like that in inferior VCSes
> because replacing the checked out trees would took forever; how cool Git
> is!).

I wrote something about this after reading #git log several days ago where somebody named Insount (sp?) was talking about "elegant idea" of the empty initial commit, but did not send it and kept silent about it. As Linus said in an earlier message, I've thought about this and am personally happy about the current way of not having it, and here is why.

Interestingly, I already talked about "show --root" in the message that I did not send -- I think you made this the right thread to post it in ;-)

-- >8 --
Subject: empty initial commit
Don't do it.  It is stupid.
	I'm imitating somebody who says "I am so right that it
        hurts".  Don't worry, I'll come back to my usual self
        and talk about what is wrong with our current tools and
        what needs to be fixed shortly ;-).
(1) Your claim that it is elegant because it removes a special
    case is bogus, because you are not removing special cases
    anyway.

The initial commit _is_ special. The first real example in "everyday" document begins by creating the initial commit out of an extracted tarball. You would _actively_ want to special case that commit. Its diff from nothingness is so uninteresting while inspecting the development history of the project that we do not even show it in "git log -p" output unless explicitly asked with "--root" option, for example [side note: we might want to default to --root for "git show", which clearly indicates that the user is interested in that particular one commit]. If you introduce the fake "epoch" commit, then you have to move that special case logic elsewhere and squelch the output when the parent is a commit with an empty tree, instead of the current logic which is to omit it when it is the root commit. You have to have special case either way.

(2) A branch yet to be born (i.e. a freshly initialized
    repository whose HEAD points at refs/heads/master that does
    not exist yet) and a branch whose tip points at a fake
    "epoch" commit are fundamentally different.

Let's remember our GIT 101. Two commits that happen to have the same tree are not equivalent, because a commit represents both the then-current state when it was made _and_ the development history that led to it. The development history is represented by chains of commits.

Earlier Linus and I updated git-pull to allow pulling into a branch yet to be born because a branch yet to be born _is_ an ancestor of any commit and can be fast-forwarded. There was no branch and there was no earlier history.

You cannot say the same thing for a branch that points at a root commit that has an empty tree. For one thing it would record authorship information and stuff so it won't be "THE universal void". You can have infinite (well, bounded by 2^160 because we use SHA-1 to name objects) such root commits, and they are not equivalent. Does that mean a true root commit (not your fake commit) can be a child of 2^160 empty parents that are all alike? Which one of them do you choose to record as its parent and why?

If you start two branches with your scheme, they will have two different fake root commits -- when merging these two branches that were independently born, should these fake root commits be treated as equivalents for merge-base computation? If so that introduces a very special case that we currently do not need in a very deep place. But we can already do a merge without common ancestor just fine (I've done one myself and Linus did two), so these 2^160 empty fake commits are not adding value to the system.

Of course, you could use "THE truly universal void" commit that is by convention created in every git repository that has some agreed-upon author/committer/log information as that fake root and uniformly use it everywhere to solve the above, to emulate what we already do. But we have been doing fine without such a fake commit, thank you.

So it's stupid to introduce such a fake commit.  Don't do it.
Now, back to my usual self.

I suspect that an independent branch creation inside an existing repository is not an everyday event, and your complaint is primarily coming from the fact that you somehow wanted to do that recently and there was not a canned way to do so, not because you need to do that very often and the tool is lacking. But for the moment, let's say it is an everyday event and making it easy to do so adds to the general value of our toolset.

I think the real shortcoming of the current set of tools is that while it allows you to be initially on a yet-to-be-born branch, it does not offer you a way to be on another yet-to-be-born branch once you created the first branch.

The command "git branch $newbranch" wants a commit to begin the newly created branch at. Another, "git checkout -b $newbranch", has the same property. If you do not give the starting commit, they conveniently defaults to HEAD, which is inconvenient for what you want.

So it _is_ cumbersome to create (or, "not to create") and be on a yet-to-be-born branch, and as a consequence, it is not possible unless you go down to bare plumbing level to start two unrelated histories in one repository. We do not give you a direct way to do that. An obvious workaround is to create a new repository to start a separate history afresh and fetch that branch in, but if an independent branch creation had a valid purpose and were an everyday event, it certainly is merely a workaround and shows that the toolset is lacking.

Maybe a new option "git checkout --void $newbranchname", which does a rough equivalent of:

	new="refs/heads/$newbranchname"
	git show-ref -q --verify "$new" &&
                die "branch $newbranchname already exists"
	# git ls-files -z | xargs -0 rm -f
        rm -f .git/index
        git symbolic-ref HEAD "$new"

is what you would want to add. I am undecided about the commented out part to remove everything from the working tree, though. On one hand, if you are running "git init-db" in a directory full of files from an extracted tarball, we would not touch any existing files, but on the other hand, since we are interested in creating a totally unrelated history, losing tracked files feels more like the right thing to do.

In any case, I suspect you need to have a bit more convincing and persuasive argument why creating and maintaining more than one, totally unrelated histories in a single repository is necessary.

And "git.git has more than one roots and it looks kinda cool" is not a convincing argument at all. For one thing, these roots were not created in a single repository. The true git root was done in Linus's dircache project back when there was no multiple branches, gitk, git-tools and gitweb were all done in their own separate repositories and later merged in to be part of the current tip of the master.

Todo, html and man roots all come from their own separate repositories and because they are not part of the history of the git development they are still independent.

The real reason I have "todo" in git.git was because the parent directory /pub/scm/git/ was not writable to me at kernel.org and I was too lazy to ask for ownership/permission changed when I took over /pub/scm/git/git.git; I otherwise would have created a separate git-todo.git next to git.git there.

And the reason html and man roots are in git.git is because having "todo" in git.git turned out to be not-so-disastrous as I feared when I first did so, and it seemed like an interesting way to experiment on the "central place to distribute unrelated stuff" idea. But they come from their own separate repositories.

By the way, I would solve B1..B100 merge issue without special casing by:

	git checkout -b merged B$(pick-randomly 1 100)
        i=1
        while test $i -le 100
        do
        	git pull . B$i
                i=$(($i + 1))
	done

Starting from a randomly picked parent and starting from an void (created with "git checkout --void" we discussed above) would give you exactly the same result because pulling B$i on top of B$i (or something that already has merged B$i) is a fast forward.

Jakub Narebski· Nov 21, 2006, 20:03 UTC · re: Junio C Hamano · lore
Junio C Hamano wrote:
Show 15 quoted lines
> Petr Baudis <pasky@suse.cz> writes:
> 
>> On Tue, Nov 21, 2006 at 07:16:44PM CET, Jakub Narebski wrote:
>>..
>>> git repo-config show.difftree --root
>>> git repo-config whatchanged.difftree --root
>>
>> That means extra pointless setup and is besides the point anyway, I was
>> asking about empty commits, not default command settings.
> 
> I agree with you.  Personally, I think:
> 
>  - show is where the user is asking for _that_ particular
>    commit, so it can safely default to --root, always.  No
>    option is needed.

We don't show patch for merges by default in git-show, so I don't see why we would want to show root commit diff in git-show by default: those two are very similar.

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Andy Parkins· Nov 23, 2006, 09:25 UTC · re: Jakub Narebski · lore
On Tuesday 2006 November 21 20:03, Jakub Narebski wrote:
> We don't show patch for merges by default in git-show, so I don't
> see why we would want to show root commit diff in git-show by default:
> those two are very similar.

$ git init-db $ date > file1 $ git add file1; git commit -a -m "file1 added" $ date > file2 $ git add file2; git commit -a -m "file2 added" $ git show --stat HEAD $ git show --stat HEAD^

I can understand while people get confused. Two patches, both add a file. git-show on one of them shows a stat; on the other it doesn't.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
Jakub Narebski· Nov 24, 2006, 07:49 UTC · re: Andy Parkins · lore
Andy Parkins wrote:
Show 16 quoted lines
> On Tuesday 2006 November 21 20:03, Jakub Narebski wrote:
> 
>> We don't show patch for merges by default in git-show, so I don't
>> see why we would want to show root commit diff in git-show by default:
>> those two are very similar.
> 
> $ git init-db
> $ date > file1
> $ git add file1; git commit -a -m "file1 added"
> $ date > file2
> $ git add file2; git commit -a -m "file2 added"
> $ git show --stat HEAD
> $ git show --stat HEAD^
> 
> I can understand while people get confused.  Two patches, both add a file.  
> git-show on one of them shows a stat; on the other it doesn't.

Well, perhaps "git show --stat" should show diffstat also for root commit, because it shows diffstat for merges (although not patch), but not patch (which usually is huge).

-- 
Jakub Narebski
Peter Baumann· Nov 23, 2006, 09:36 UTC · re: Junio C Hamano · lore

[PATCH] config option core.showroot to enable showing the diff of the root commit

This allows one to see the root commit as a diff in commands like git-log, git-show and git-whatchanged. It also modifies git-diff-tree to act as --root was specified on the commandline. The default is set to true.

Signed-off-by: Peter Baumann <Peter.B.Baumannn@stud.informatik.uni-erlangen.de>
---
I'm not sure if making core.showroot acting on git-diff-tree is the
right thing to do. Please check first bevore applying.
 Documentation/config.txt |    6 ++++++
 builtin-diff-tree.c      |    1 +
 builtin-log.c            |    3 +++
 cache.h                  |    1 +
 config.c                 |    5 +++++
 environment.c            |    1 +
 6 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 9d3c71c..7e600ca 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -110,6 +110,12 @@ core.legacyheaders::
 	database directly (where the "http://" and "rsync://" protocols
 	count as direct access).
 
+core.showroot::
+	If true, the initial commit will be shown as a big creation event.
+	This is equivalent to a diff against an empty tree.
+	Tools like gitlink:git-log[1] or gitlink:git-whatchanged[1], which
+	normally hide the root commit will now show it. True by default.
+
 alias.*::
 	Command aliases for the gitlink:git[1] command wrapper - e.g.
 	after defining "alias.last = cat-file commit HEAD", the invocation
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c
index 24cb2d7..d58b7ca 100644
--- a/builtin-diff-tree.c
+++ b/builtin-diff-tree.c
@@ -72,6 +72,7 @@ int cmd_diff_tree(int argc, const char *
 	nr_sha1 = 0;
 	opt->abbrev = 0;
 	opt->diff = 1;
+	opt->show_root_diff = show_root_diff;
 	argc = setup_revisions(argc, argv, opt, NULL);
 
 	while (--argc > 0) {
diff --git a/builtin-log.c b/builtin-log.c
index fedb013..9541c7d 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -53,6 +53,7 @@ int cmd_whatchanged(int argc, const char
 	rev.diff = 1;
 	rev.diffopt.recursive = 1;
 	rev.simplify_history = 0;
+	rev.show_root_diff = show_root_diff;
 	cmd_log_init(argc, argv, prefix, &rev);
 	if (!rev.diffopt.output_format)
 		rev.diffopt.output_format = DIFF_FORMAT_RAW;
@@ -72,6 +73,7 @@ int cmd_show(int argc, const char **argv
 	rev.always_show_header = 1;
 	rev.ignore_merges = 0;
 	rev.no_walk = 1;
+	rev.show_root_diff = show_root_diff;
 	cmd_log_init(argc, argv, prefix, &rev);
 	return cmd_log_walk(&rev);
 }
@@ -83,6 +85,7 @@ int cmd_log(int argc, const char **argv,
 	git_config(git_diff_ui_config);
 	init_revisions(&rev, prefix);
 	rev.always_show_header = 1;
+	rev.show_root_diff = show_root_diff;
 	cmd_log_init(argc, argv, prefix, &rev);
 	return cmd_log_walk(&rev);
 }
diff --git a/cache.h b/cache.h
index f2ec5c8..feff2bd 100644
--- a/cache.h
+++ b/cache.h
@@ -191,6 +191,7 @@ extern int warn_ambiguous_refs;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
 extern int zlib_compression_level;
+extern int show_root_diff;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
diff --git a/config.c b/config.c
index 3cae390..dd720b5 100644
--- a/config.c
+++ b/config.c
@@ -319,6 +319,11 @@ int git_default_config(const char *var,
 		return 0;
 	}
 
+	if (!strcmp(var, "core.showroot")) {
+		show_root_diff = git_config_bool(var, value);
+		return 0;
+	}
+
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
 }
diff --git a/environment.c b/environment.c
index 84d870c..71099f4 100644
--- a/environment.c
+++ b/environment.c
@@ -24,6 +24,7 @@ const char *apply_default_whitespace;
 int zlib_compression_level = Z_DEFAULT_COMPRESSION;
 int pager_in_use;
 int pager_use_color = 1;
+int show_root_diff = 1;
 
 static const char *git_dir;
 static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
-- 
1.4.3.3
Junio C Hamano· Nov 23, 2006, 20:52 UTC · re: Peter Baumann · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de> writes:

Show 8 quoted lines
> This allows one to see the root commit as a diff in commands like git-log,
> git-show and git-whatchanged. It also modifies git-diff-tree to act as --root
> was specified on the commandline. The default is set to true.
>
> Signed-off-by: Peter Baumann <Peter.B.Baumannn@stud.informatik.uni-erlangen.de>
> ---
> I'm not sure if making core.showroot acting on git-diff-tree is the
> right thing to do. Please check first bevore applying.

I agree that this "use --root by default" belongs to Porcelain layer, not the plumbing. We would probably want to do this in the same way as we do the color in diff.c::git_diff_ui_config().

Peter Baumann· Nov 23, 2006, 23:34 UTC · re: Junio C Hamano · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

On 2006-11-23, Junio C Hamano <junkio@cox.net> wrote:
Show 16 quoted lines
> Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de>
> writes:
>
>> This allows one to see the root commit as a diff in commands like git-log,
>> git-show and git-whatchanged. It also modifies git-diff-tree to act as --root
>> was specified on the commandline. The default is set to true.
>>
>> Signed-off-by: Peter Baumann <Peter.B.Baumannn@stud.informatik.uni-erlangen.de>
>> ---
>> I'm not sure if making core.showroot acting on git-diff-tree is the
>> right thing to do. Please check first bevore applying.
>
> I agree that this "use --root by default" belongs to Porcelain
> layer, not the plumbing.  We would probably want to do this in
> the same way as we do the color in diff.c::git_diff_ui_config().
>

Sorry, but I don't understand. The color handling doesn't look any different to me than the handling of the other config entrys. Did I miss something?

Peter
Junio C Hamano· Nov 24, 2006, 00:18 UTC · re: Peter Baumann · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de> writes:

Show 9 quoted lines
>>> I'm not sure if making core.showroot acting on git-diff-tree is the
>>> right thing to do. Please check first bevore applying.
>>
>> I agree that this "use --root by default" belongs to Porcelain
>> layer, not the plumbing.  We would probably want to do this in
>> the same way as we do the color in diff.c::git_diff_ui_config().
>>
> Sorry, but I don't understand. The color handling doesn't look any different
> to me than the handling of the other config entrys. Did I miss something?

"git-diff-tree --color HEAD" (with explicit command line instruction to color it) still colours its output, but "[diff] color = auto" in ~/.gitconfig would not affect the coloring. Hence, "git-diff-tree HEAD" with the configuration entry gives monochrome.

"git diff HEAD" on the other hand looks at '[diff] color = auto" and will color its output without being told on the command line.

Junio C Hamano· Nov 24, 2006, 01:30 UTC · re: Junio C Hamano · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

Junio C Hamano <junkio@cox.net> writes:
Show 15 quoted lines
> Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de>
> writes:
>
>> Sorry, but I don't understand. The color handling doesn't look any different
>> to me than the handling of the other config entrys. Did I miss something?
>
> "git-diff-tree --color HEAD" (with explicit command line
> instruction to color it) still colours its output, but "[diff]
> color = auto" in ~/.gitconfig would not affect the coloring.
> Hence, "git-diff-tree HEAD" with the configuration entry gives
> monochrome.
>
> "git diff HEAD" on the other hand looks at '[diff] color = auto"
> and will color its output without being told on the command
> line.

Since this is about "log" family that deals with revision structure, how about....

-- >8 -- [PATCH] config option log.showroot to show the diff of root commits

From: Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de>

This allows one to see a root commit as a diff in commands like git-log, git-show and git-whatchanged.

Signed-off-by: Peter Baumann <Peter.B.Baumannn@stud.informatik.uni-erlangen.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 Documentation/config.txt |    6 ++++++
 builtin-log.c            |   20 ++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 9d3c71c..9090762 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -219,6 +219,12 @@ i18n.commitEncoding::
 	browser (and possibly at other places in the future or in other
 	porcelains). See e.g. gitlink:git-mailinfo[1]. Defaults to 'utf-8'.
 
+log.showroot::
+	If true, the initial commit will be shown as a big creation event.
+	This is equivalent to a diff against an empty tree.
+	Tools like gitlink:git-log[1] or gitlink:git-whatchanged[1], which
+	normally hide the root commit will now show it. True by default.
+
 merge.summary::
 	Whether to include summaries of merged commits in newly created
 	merge commit messages. False by default.
diff --git a/builtin-log.c b/builtin-log.c
index fedb013..7acf5d3 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -13,6 +13,8 @@
 #include <time.h>
 #include <sys/time.h>
 
+static int default_show_root = 1;
+
 /* this is in builtin-diff.c */
 void add_head(struct rev_info *revs);
 
@@ -22,6 +24,7 @@ static void cmd_log_init(int argc, const
 	rev->abbrev = DEFAULT_ABBREV;
 	rev->commit_format = CMIT_FMT_DEFAULT;
 	rev->verbose_header = 1;
+	rev->show_root_diff = default_show_root;
 	argc = setup_revisions(argc, argv, rev, "HEAD");
 	if (rev->diffopt.pickaxe || rev->diffopt.filter)
 		rev->always_show_header = 0;
@@ -44,11 +47,20 @@ static int cmd_log_walk(struct rev_info
 	return 0;
 }
 
+static int git_log_config(const char *var, const char *value)
+{
+	if (!strcmp(var, "log.showroot")) {
+		default_show_root = git_config_bool(var, value);
+		return 0;
+	}
+	return git_diff_ui_config(var, value);
+}
+
 int cmd_whatchanged(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info rev;
 
-	git_config(git_diff_ui_config);
+	git_config(git_log_config);
 	init_revisions(&rev, prefix);
 	rev.diff = 1;
 	rev.diffopt.recursive = 1;
@@ -63,7 +75,7 @@ int cmd_show(int argc, const char **argv
 {
 	struct rev_info rev;
 
-	git_config(git_diff_ui_config);
+	git_config(git_log_config);
 	init_revisions(&rev, prefix);
 	rev.diff = 1;
 	rev.diffopt.recursive = 1;
@@ -80,7 +92,7 @@ int cmd_log(int argc, const char **argv,
 {
 	struct rev_info rev;
 
-	git_config(git_diff_ui_config);
+	git_config(git_log_config);
 	init_revisions(&rev, prefix);
 	rev.always_show_header = 1;
 	cmd_log_init(argc, argv, prefix, &rev);
@@ -109,7 +121,7 @@ static int git_format_config(const char
 	if (!strcmp(var, "diff.color")) {
 		return 0;
 	}
-	return git_diff_ui_config(var, value);
+	return git_log_config(var, value);
 }
 
 
-- 
1.4.4.1.g77614
Peter Baumann· Nov 24, 2006, 07:53 UTC · re: Junio C Hamano · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

On 2006-11-24, Junio C Hamano <junkio@cox.net> wrote:
Show 15 quoted lines
>> "git-diff-tree --color HEAD" (with explicit command line
>> instruction to color it) still colours its output, but "[diff]
>> color = auto" in ~/.gitconfig would not affect the coloring.
>> Hence, "git-diff-tree HEAD" with the configuration entry gives
>> monochrome.
>>
>> "git diff HEAD" on the other hand looks at '[diff] color = auto"
>> and will color its output without being told on the command
>> line.
>
> Since this is about "log" family that deals with revision
> structure, how about....
>
> -- >8 --
> [PATCH] config option log.showroot to show the diff of root commits
[...]
Patch looks good.

One question, what's the difference between git-log -p and git-whatchanged -p? I could only see it differ in the root commit handling.

Interesting parts marked with | as first character of the line.
  git-repo-config --get log.showroot
  false
  git-log -p 8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
  commit 8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
  Author: Linus Torvalds <torvalds@ppc970.osdl.org>
  Date:   Thu Apr 7 15:16:10 2005 -0700
      Add copyright notices.
      The tool interface sucks (especially "committing" information, which is just
      me doing everything by hand from the command line), but I think this is in
      theory actually a viable way of describing the world. So copyright it.
  diff --git a/cat-file.c b/cat-file.c
  index 74a0a23..d8f0121 100644
  --- a/cat-file.c
  +++ b/cat-file.c
  @@ -1,3 +1,8 @@
  +/*
  + * GIT - The information manager from hell
  + *
  + * Copyright (C) Linus Torvalds, 2005
  + */
   #include "cache.h"
   int main(int argc, char **argv)
  [... rest of the diff ...]
| commit e83c5163316f89bfbde7d9ab23ca2e25604af290
| Author: Linus Torvalds <torvalds@ppc970.osdl.org>
| Date:   Thu Apr 7 15:13:13 2005 -0700
|
|     Initial revision of "git", the information manager from hell
|
  [ ... as specified in log.showroot, no diff of the root commit ...]
  git-whatchanged -p 8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
  commit 8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
  Author: Linus Torvalds <torvalds@ppc970.osdl.org>
  Date:   Thu Apr 7 15:16:10 2005 -0700
  
      Add copyright notices.
      
      The tool interface sucks (especially "committing" information, which is just
      me doing everything by hand from the command line), but I think this is in
      theory actually a viable way of describing the world. So copyright it.
  
  diff --git a/cat-file.c b/cat-file.c
  index 74a0a23..d8f0121 100644
  --- a/cat-file.c
  +++ b/cat-file.c
  @@ -1,3 +1,8 @@
  +/*
  + * GIT - The information manager from hell
  + *
  + * Copyright (C) Linus Torvalds, 2005
  + */
   #include "cache.h"
   
   int main(int argc, char **argv)
  [... rest of the diff ...]
|
| [ ... no commit message etc from the root commit is shown ...]
|

As you can see, the root commit isn't shown. Is this intentional? Or is it just me not getting the different meaning of git-log and git-whatchanged?

Setting "log.showroot = true" the output of the 2 commands is identical.
Peter
Junio C Hamano· Nov 24, 2006, 08:54 UTC · re: Peter Baumann · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de> writes:

> One question, what's the difference between git-log -p and
> git-whatchanged -p?
> ...
> As you can see, the root commit isn't shown. Is this intentional?
Some historical background.

The traditional command do do log-minded things was whatchanged and it was implemented as

	git rev-list $revision_args -- $path_limits |
        git diff-tree --stdin --pretty -r $format_args

and whatchanged did not give --root to diff-tree by default. And 'diff-tree' does not show --pretty logs when there is no diff to be shown (which still is true today and is a useful behaviour), hence no mention of the root commit.

On the other hand, "git-log" traditionally looked like this:
	git rev-list --pretty $revision_args 

Back then, there was no path_limits nor even diff options to it.

Later, Linus (with help from others) made the revision walk machinery as callable inside programs other than "rev-list", eliminating the need to pipe rev-list into diff-tree to perform log-minded things. That enriched what "git log" can do, and mostly made "whatchanged" a redundant command. As you may have noticed, there isn't much difference between these two commands in builtin-log.c; their differences are solely what default options for diff and revision machinery are used and are meant to match the traditional behaviour of these commands.

So there shouldn't be any differences, really, when you override their defaults with the likes of -p.

Honestly speaking, I do not think there was _any_ consciously designed intention to handle root commits, either to make these commands behave identically or differently; regarding parentless commits, they just behave the way they happen to behave, because root commits were not something either Linus nor I were interested in.

Given the recent discussion, however, the intention now should be that Porcelain level commands should default to do --root (i.e. when asked to do "diff" to show how a commit without a parent differs from its nonexistent parent, show diff with emptiness).

Peter Baumann· Nov 24, 2006, 09:04 UTC · re: Junio C Hamano · lore

Re: [PATCH] config option core.showroot to enable showing the diff of the root commit

On 2006-11-24, Junio C Hamano <junkio@cox.net> wrote:
Show 54 quoted lines
> Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de>
> writes:
>
>> One question, what's the difference between git-log -p and
>> git-whatchanged -p?
>> ...
>> As you can see, the root commit isn't shown. Is this intentional?
>
> Some historical background.
>
> The traditional command do do log-minded things was whatchanged
> and it was implemented as
>
> 	git rev-list $revision_args -- $path_limits |
>         git diff-tree --stdin --pretty -r $format_args
>
> and whatchanged did not give --root to diff-tree by default.
> And 'diff-tree' does not show --pretty logs when there is no
> diff to be shown (which still is true today and is a useful
> behaviour), hence no mention of the root commit.
>
> On the other hand, "git-log" traditionally looked like this:
>
> 	git rev-list --pretty $revision_args 
>
> Back then, there was no path_limits nor even diff options to
> it.
>
> Later, Linus (with help from others) made the revision walk
> machinery as callable inside programs other than "rev-list",
> eliminating the need to pipe rev-list into diff-tree to perform
> log-minded things.  That enriched what "git log" can do, and
> mostly made "whatchanged" a redundant command.  As you may have
> noticed, there isn't much difference between these two commands
> in builtin-log.c; their differences are solely what default
> options for diff and revision machinery are used and are meant
> to match the traditional behaviour of these commands.
>
> So there shouldn't be any differences, really, when you override
> their defaults with the likes of -p.
>
> Honestly speaking, I do not think there was _any_ consciously
> designed intention to handle root commits, either to make these
> commands behave identically or differently; regarding parentless
> commits, they just behave the way they happen to behave, because
> root commits were not something either Linus nor I were
> interested in.
>
> Given the recent discussion, however, the intention now should
> be that Porcelain level commands should default to do --root
> (i.e.  when asked to do "diff" to show how a commit without a
> parent differs from its nonexistent parent, show diff with
> emptiness).
>
Ah. I see. Thanks for the clarification.
Peter
Carl Worth· Nov 21, 2006, 18:39 UTC · re: Linus Torvalds · lore
On Tue, 21 Nov 2006 08:31:30 -0800 (PST), Linus Torvalds wrote:
> I suspect we should make the thing a config option, and default it to
> "on".
Agreed. That would be fabulous!
Show 5 quoted lines
> That's really the reason why git defaults to not showing the root diff at
> all: exactly because for the kernel, the initial commit was state that
> "just came to be", and I found it both illogical and annoying to see it as
> a diff, since that commit really was a "black hole" where previous history
> just disappeared.
Ah, that's a rationale I wouldn't have guessed.
> There's also another reason for the root being special, which is purely
> git-internal: the root really has no parents at all, and the normal "git
> diff" is "diff against parents".

This is the rationale I was guessing was the cause. It clearly takes a special case in the code to show the root diff, and --root seemed like that special-case implementation leaking into the interface, (where, usually, the user wouldn't expect the first commit to be any different than any other).

This looks like yet another case where a feature was added, and a new command-line option with it, when what was really wanted was a new default.

> git didn't end up doing that (and I'm personally pretty happy about it),

It seems a reasonable enough decision, but it does have some impacts. Several of the tools don't work in the strange state between git-init and the first git-commit. Some of these are getting worked out now, (such as pull), but Junio was still objecting to fixing diff to work.

There's a decision to have git's internals support this intermediate state, but all the tools should be made completely functional. This is an important things to get right, since this is the first state in which a new user will have her repository, (right after doing git-init-db as the first step in the tutorial). So it's important to make this state functional and not have to explain the "strange" implementation details "Normally, you would have a branch HEAD at this point, so these commands would usually work even though they don't yet, etc. etc."

> So having a config option would solve the problem,
If the default is fixed, yes.
Show 6 quoted lines
>                                                    but what annoys me
> right now about the config options is that we really should have a
> graphical front-end to setting those things or something, because while
> _I_ don't have any issues with editing a ".git/config" file, I think we're
> getting to the point where a lot of our problems are really about "you can
> do it, but you have to know a lot about git to even know you can do it".

I agree with that statement. But I also think that for the "new user problems" a new graphical tool for twiddling git options wouldn't make the system any less imposing. On the other hand, getting the defaults to be less surprising would definitely help, (and configuration options can be used to good effect to allow "old-timers" to maintain the behavior they're used to as defaults change).

-Carl
Junio C Hamano· Nov 21, 2006, 19:15 UTC · re: Linus Torvalds · lore
Linus Torvalds <torvalds@osdl.org> writes:
Show 20 quoted lines
> On Tue, 21 Nov 2006, Peter Baumann wrote:
>> 
>> Why not make --root the default? I also stumbled over this behaviour and
>> even asked on this list.
>
> I suspect we should make the thing a config option, and default it to 
> "on".
>
> I personally do _not_ want to see the root commit, because for the kernel, 
> it's a honking huge import that does not make sense as a "diff". It's not 
> really a diff against anything, after all - it's an import.
>
> That's really the reason why git defaults to not showing the root diff at 
> all: exactly because for the kernel, the initial commit was state that 
> "just came to be", and I found it both illogical and annoying to see it as 
> a diff, since that commit really was a "black hole" where previous history 
> just disappeared.
>
> But if you have the _full_ history with a new project, "--root" by default 
> probably makes tons of sense.
I agree fully with the above.  Let's make it happen.

← back to recent threads