Git development
 help / color / mirror / Atom feed
* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links
From: Junio C Hamano @ 2006-04-25  5:16 UTC (permalink / raw)
  To: Sam Vilain; +Cc: git
In-Reply-To: <20060425035421.18382.51677.stgit@localhost.localdomain>

Sam Vilain <sam.vilain@catalyst.net.nz> writes:

> Examples of use cases this helps:

My reaction to this patch series is that you try to cover quite
different and unrelated things, without thinking things through,
and end up covering nothing usefully.  What is missing in these
"use cases" is a coherent semantics.

What the "prior" means to humans and tools.  And my *guess* of
what they mean suggests you are trying to make it mean many
unrelated concepts.

>  1. heads that represent topic branch merges
>
>     This is the "pu" branch case, where the head is a merge of several
>     topic branches that is continually moved forward.

For usage like "pu", the previous "pu" head could be recorded as
one of the parents; you do not need anything special.

The reason I do not include the previous head when I reconstruct
"pu" is because I explicitly *want* to drop history -- not
having to carry forward a failed experiment is what is desired
there.  Otherwise I would manage "pu" just like I currently do
"next" and "master".  So this is not a justification to add
something new.

>  2. revising published commits / re-basing
>
>     This is what "stg" et al do.  The tools allow you to commit,
>     rewind, revise, recommit, fast forward, etc.

stg wants to have a link to the fork-point commit.  I do not
know if it is absolutely necessary (you might be able to figure
it out using merge-base, I dunno).

>     In this case, the "prior" link would point to the last revision of
>     a patch.  Tools would probably

Probably what...???

>  3. sub-projects
>
>     In this case, the commit on the "main" commit line would have a
>     "prior" link to the commit on the sub-project.  The sub-project
>     would effectively be its own head with copied commits objects on
>     the main head.

You say you can have only one "prior" per commit, which makes
this unsuitable to bind multiple subprojects into a larger
project (the earlier "bind" proposal allows zero or more).

When you, a human, see a "prior" link in "git cat-file commit"
output, what does that tell you?  Is it "the previous commit
this thing replaces?"  Or is it a commit in a different line of
development which is its subproject?  Or is it a commit that was
cherry-picked from a different line?  How would you tell?  And
assuming you _could_ somehow tell, how would it help you to know
it?

When the Plumbing and the Porcelain sees a "prior" link, what
should they do?  It hugely depends on what that link means.  You
have a patch to merge-base to include the prior commit of the
commit in question in the ancestry chain, but that is probably
valid only for case 1. and perhaps 2. If the link points at a
commit of otherwise unrelated subproject head, you would _never_
want to include that in the merge-base computation.  Neither the
"this commit was taken out of context from otherwise unrelated
branch" link you envision to use for 4.  I think including
"prior" to ancestry list for case 1. and 2. makes some sense in
the merge-base example only because (1) it does not have to be any
different from an ordinary "parent" to begin with for case 1.,
and (2) it points at fork-point which is sort of a merge-base
already.

There may be some narrower concrete use case for which you can
devise coherent semantics, and teach tools and humans how to
interpret such inter-commit relationship that are _not_
parent-child ancestry.  For example, if you have one special
link to point at a "cherry-picked" commit, rebasing _could_ take
advantage of it.  When your side branch tip is at D, and commit
D has "this was cherry-picked from commit E" note, and if you
are rebasing your work on top of F:

        A---B---C---D
       /
  o---o---E---F

the tool can notice that F can reach E and carry forward only A,
B, and C on top of F, omitting D.  So having such a link might
be useful.  But if that is what you are going to do, I do not
think you would want to conflate that with other inter-commit
relationships, such as "previous hydra cap".

Oh, and you would need an update to rev-list --objects and
fsck-objects if you are to add any new link to commit objects.
Otherwise fetch/push would not get the related commits prior
points at, and prune will happily discard them.  But before even
bothering it, you need to come up with a semantics first.

^ permalink raw reply

* Re: [PATCH 1/5] add 'prior' link in commit structure
From: Junio C Hamano @ 2006-04-25  5:18 UTC (permalink / raw)
  To: git
In-Reply-To: <20060425043106.18382.24344.stgit@localhost.localdomain>

Sam Vilain <sam.vilain@catalyst.net.nz> writes:

> For now this is just recorded as a char* pointer, as it is not an
> error condition for the commit not to be present locally.

Object ancestry is parsed lazily, so you should not have to do this.
Just point at another commit if you are to have only one (I
recommend against it) or have another commit_list, but when you
instantiate you may want to have a flag in the commit object
itself that says "this need not exist".

^ permalink raw reply

* Re: [PATCH 2/5] git-merge-base: follow 'prior' links to find merge bases
From: Junio C Hamano @ 2006-04-25  5:19 UTC (permalink / raw)
  To: Sam Vilain; +Cc: git
In-Reply-To: <20060425043106.18382.48165.stgit@localhost.localdomain>

Sam Vilain <sam.vilain@catalyst.net.nz> writes:

> From: Sam Vilain <sam.vilain@catalyst.net.nz>
>
> It is possible that a good merge base may be found looking via "prior"
> links as well.  We follow them where possible.

You need to define what "prior" means before making decision
like that.  If "prior" can mean cherry-picked one from unrelated
line of development, the above reasoning does not apply.

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Jakub Narebski @ 2006-04-25  6:44 UTC (permalink / raw)
  To: git
In-Reply-To: <20060425035421.18382.51677.stgit@localhost.localdomain>

Sam Vilain wrote:

> This patch series implements "prior" links in commit objects.  A
> 'prior' link on a commit represents its historical precedent, as
> opposed to the previous commit(s) that this commit builds upon.
> 
> This is a proof of concept only; there is an outstanding bug (I put
> the prior header right after parent, when it should really go after
> author/committer), and room for improvement no doubt remain elsewhere.
> Not to mention my shocking C coding style ;)

I think "prior" link concept is to generic and is used for quite unrelated
things

> Examples of use cases this helps:
> 
>  1. heads that represent topic branch merges
> 
>     This is the "pu" branch case, where the head is a merge of several
>     topic branches that is continually moved forward.
> 
>     topic branches     head
>       ,___.   ,___.
>      | TA1 | | TB1 |
>       `---'   `---'    ,__.
>          ^\_____^\____| H1 |
>                        `--'
> 
>     + some topic branch changes and a republish:
> 
>       ,___.   ,___.
>      | TA1 | | TB1 |
>       `---'   `---'^   ,__.
>         |^\_____^\____| H1 |
>         |       |      `--'
>       ,_|_.   ,_|_.      P
>      | TA2 | | TB2 |     |
>       `---'   `---'^     |
>         ^       ^        |
>       ,_|_.     |        |
>      | TA3 |    |        |
>       `---'     |      ,__.
>          ^\______\____| H2 |
>                        `--'
> 
>     key:  ^ = parent   P = prior

This case is clear. You want to record previous head of "pu"-like branch,
but you also want to drop the history, so you don't want to record it as
one of parents. I'm not sure if this link would be informative only, or if
it could be usefull e.g. in merge computing.
 
>  2. revising published commits / re-basing
> 
>     This is what "stg" et al do.  The tools allow you to commit,
>     rewind, revise, recommit, fast forward, etc.
> 
>     In this case, the "prior" link would point to the last revision of
>     a patch.  Tools would probably support only doing this for selected, 
>     "published" patch chains 

This case is quite different. If I understand it correctly prior either
points to the previous patch in patch stack, or the bottom of the
stack/patch stack attachment point. If this cannot be computed easily, it
could I guess be added, but perhaps using other name for link.

>  3. sub-projects
> 
>     In this case, the commit on the "main" commit line would have a
>     "prior" link to the commit on the sub-project.  The sub-project
>     would effectively be its own head with copied commits objects on
>     the main head.
>
>  4. tracking cherry picking
> 
>     In this case, the "prior" link just points to the commit that was
>     cherry picked.  This is perhaps a little different, but an idea
>     that somebody else had for this feature.

Those two are yet another case altogether, the "prior" link pointing to "the
same" commit in another history line. I agree with Junio that for (3)
"bind" proposal (if I understand correctly it points to tree rather than to
commit) is more clean way to go. As to cherry picking (and perhaps
"cherry-pick on steroids" aka rebase), there is truly 0-1 relation (either
this link is not needed at all, or there is only one commit to link to),
but I don't think it should have the same name as in case (1), as this is
very different. And there is a problem that the link might be dangling if
we deleted the branch we cherry-picked commit from, or did some history
rewrite. Perhaps "cherry" would be better name for this link :-)

Additionally for each of those cases we have to consider how to compute the
link and which commands should be modified, which commands can make use of
the link and should be modified, should the link be to commit, tag, tree or
blob, what we want to do with link when pulling/pushing/cloning into
another repository and which commands should be modified. Not only use case
scenarios.

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Junio C Hamano @ 2006-04-25  7:29 UTC (permalink / raw)
  To: git; +Cc: jnareb
In-Reply-To: <e2kgga$d7q$1@sea.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> Additionally for each of those cases we have to consider how to compute the
> link and which commands should be modified, which commands can make use of
> the link and should be modified, should the link be to commit, tag, tree or
> blob, what we want to do with link when pulling/pushing/cloning into
> another repository and which commands should be modified. Not only use case
> scenarios.

This last paragraph is a very good suggestion.  The alleged "use
cases" are just laudary list of wishes, if they are not
accompanied by descriptions on what the modified data structure
and added attribute _means_ and how they are _used_.

Here is a related but not necessarily competing idle thought.

How about an ability to "attach" arbitrary objects to commit
objects?  The commit object would look like:

    tree 0aaa3fecff73ab428999cb9156f8abc075516abe
    parent 5a6a8c0e012137a3f0059be40ec7b2f4aa614355
    parent e1cbc46d12a0524fd5e710cbfaf3f178fc3da504
    related a0e7d36193b96f552073558acf5fcc1f10528917 key
    related 0032d548db56eac9ea09b4ba05843365f6325b85 cherrypick
    author Junio C Hamano <junkio@cox.net> 1145943079 -0700
    committer Junio C Hamano <junkio@cox.net> 1145943079 -0700

    Merge branch 'pb/config' into next

    * pb/config:
      Deprecate usage of git-var -l for getting config vars list
      git-repo-config --list support

The format of "related" attribute is, keyword "related", SP, 40-byte
hexadecimal object name, SP, and arbitrary sequence of bytes
except LF and NUL.  Let's call this arbitrary sequence of bytes
"the nature of relation".

The semantics I would attach to these "related" links are as
follows:

 * To the "core" level git, they do not mean anything other than
   "you must to have these objects, and objects reachable from
   them, if you are going to have this commit and claim your
   repository is without missing objects".

That means "git-rev-list --objects" needs to list these objects
(and if they are tags, commits, and trees, then what are
reachable from them), and "git-fsck" needs to consider these
related objects and objects reachable from them are reachable
from this commit.  NOTHING ELSE NEEDS TO BE DONE by the core
(obviously, cat-file needs to show them, and commit-tree needs to
record them, but that goes without saying).

Then porcelains can agree on what different kinds of nature of
relation mean and do sensible things.  The earlier "omit the
cherry-picked ones" example I gave can examine "cherrypick".

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Jakub Narebski @ 2006-04-25  7:43 UTC (permalink / raw)
  To: git
In-Reply-To: <7v7j5e2jv7.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:

> Here is a related but not necessarily competing idle thought.
> 
> How about an ability to "attach" arbitrary objects to commit
> objects?  The commit object would look like:
> 
>     tree 0aaa3fecff73ab428999cb9156f8abc075516abe
>     parent 5a6a8c0e012137a3f0059be40ec7b2f4aa614355
>     parent e1cbc46d12a0524fd5e710cbfaf3f178fc3da504
>     related a0e7d36193b96f552073558acf5fcc1f10528917 key
>     related 0032d548db56eac9ea09b4ba05843365f6325b85 cherrypick
>     author Junio C Hamano <junkio@cox.net> 1145943079 -0700
>     committer Junio C Hamano <junkio@cox.net> 1145943079 -0700
> 
>     Merge branch 'pb/config' into next
> 
>     * pb/config:
>       Deprecate usage of git-var -l for getting config vars list
>       git-repo-config --list support
> 
> The format of "related" attribute is, keyword "related", SP, 40-byte
> hexadecimal object name, SP, and arbitrary sequence of bytes
> except LF and NUL.  Let's call this arbitrary sequence of bytes
> "the nature of relation".
> 
> The semantics I would attach to these "related" links are as
> follows:
> 
>  * To the "core" level git, they do not mean anything other than
>    "you must to have these objects, and objects reachable from
>    them, if you are going to have this commit and claim your
>    repository is without missing objects".
> 
> That means "git-rev-list --objects" needs to list these objects
> (and if they are tags, commits, and trees, then what are
> reachable from them), and "git-fsck" needs to consider these
> related objects and objects reachable from them are reachable
> from this commit.  NOTHING ELSE NEEDS TO BE DONE by the core
> (obviously, cat-file needs to show them, and commit-tree needs to
> record them, but that goes without saying).

Perhaps there should be an option to specify that the link is optional, and
the object pointed can be gone missing. For example for cherrypick the
original cherry-picked commit can either be removed completely, e.g. when
the original branch is deleted, or it can be modified breaking link when we
rewrite history up to original commit on original branch.

Also all other commands which show commit (commit messsage at least) should
be considered for including "related" links...

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [BUG] gitk draws a wrong line
From: Uwe Zeisberger @ 2006-04-25  7:54 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <17485.31716.452326.229628@cargo.ozlabs.ibm.com>

Hello Paul,

Paul Mackerras wrote:
> Uwe Zeisberger writes:
> 
> > and then going to commit 10c2df65060e1ab57b2f75e0749de0ee9b8f4810, 
> > I see a small superfluous line between the two commits under 10c2df.
> > 
> > But still worse, if I select the line going down from 10c2df and then
> > select it's parent (i.e c76b6b) I get a big line ending in the commit
> > descriptions and four lines ending in midair.
> 
> That is an X server bug, it seems.  Tk already clips vertices that it
> sends to the X server to be within a box that is no more than 32000
> pixels wide or high, but that seems not to be enough with some X
> servers.  What X server version are you using and what sort of video
> card?
It's a Debian system with XFree 4.3.0.dfsg.1-14 and according to lspci I
have

	0000:01:00.0 VGA compatible controller: ATI Technologies Inc Radeon RV100 QY [Radeon 7000/VE]

> If you're feeling adventurous, you can rebuild Tk with the patch below
> (courtesy of D. Richard Hipp) and see if that fixes it.  If it does it
> proves that it is an X server bug.
OK, I tried that and it helped. 

I list my steps for people who want to "fix" it, too:

	Note: You need a deb-src line in your sources.list.  Moreover
	some packages are assumed to be installed (e.g. devscripts,
	fakeroot, vim :-))

	~$ mkdir src; cd src
	~/src$ apt-get build-dep tk8.4
	~/src$ apt-get source tk8.4
	~/src$ cd tk8.4-8.4.12
	~/src/tk8.4-8.4.12$ vim generic/tkCanvUtil.c

	[ apply the patch provided by Paul/D. Richard Hipp ]

	~/src/tk8.4-8.4.12$ dch -n

	[ write a sensible changelog entry ]

	~/src/tk8.4-8.4.12$ fakeroot dpkg-buildpackage
	...

	~/src/tk8.4-8.4.12$ cd ..
	~/src$ sudo dpkg -i tk8.4_8.4.12-1.1_i386.deb

I'm not entirely clear what this patch does.  From only reading it, I
assume it should only have an effect on rather big windows, right?

Do you know some more details about the bug?  Do you know to who it
should get reported?

Thanks for your help
Uwe

-- 
Uwe Zeisberger

http://www.google.com/search?q=gravity+on+earth%3D

^ permalink raw reply

* [ANNOUNCE] GIT 1.3.1
From: Junio C Hamano @ 2006-04-25  8:04 UTC (permalink / raw)
  To: git; +Cc: linux-kernel

The latest maintenance release GIT 1.3.1 is available at the
usual places:

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

	git-1.3.1.tar.{gz,bz2}			(tarball)
	RPMS/$arch/git-*-1.3.1-1.$arch.rpm	(RPM)

Just to let people who are new to the game know, 1.3.X (1<=X)
series is purely bugfix maintenance on top of 1.3.0 release, and
no new features will be added unless there is a compelling
reason (think of them like 2.6.16.X releases of the kernel,
slightly looser updates criteria).

There are four primary branches in git.git repository.

 * Releases in the 1.3.X series come from the "maint" branch, which
   was forked at 1.3.0.

 * All the new features and improvements start their life as
   topic branches that are merged to the "pu" (proposed updates)
   branch.  They are often incomplete and/or unstable.  You can
   think of "pu" as the -mm.

 * When these topic branches become stable enough, they are
   merged into "next" branch.  I personally run "next" branch
   for my work to trust my data to it, until very close to the
   next feature release.

 * After being cooked for a few days to a week in "next", these
   good changes graduate to the "master" branch.  Some of them
   die while being cooked there, but that does not happen very
   often (bad apples are culled while in "pu").

I make feature release out of "master" branch periodically,
which are tagged as X.Y.0 releases.  At that point, "maint"
branch is forked to prepare X.Y.1 and onward.

If you are an end user, the "maint" releases are the recommended
stale releases, but you could miss out new features quickly.
Please do send in bug reports for them, but do not expect new
cool features to appear there.

If you want to stay current and stable, I would recommend to
track "master".

If you are a git developer, being aware of what is happening in
"next" would often be very helpful.  The infrastructure you plan
to base your change on may be in the process of being updated
and your changes to "master" can become useless when that
happens.

If you are a truly devoted git hacker, picking what is in "pu"
can be exciting and useful from time to time.

Post 1.3.0 "master" branch development currently contains major
rewrite of log/show/whatchanged infrastructure, and will be
getting updated pack-objects, faster write-tree, consolidated
"git diff" that is not a shell script, and hopefully many
others.  To reiterate, they will be part of 1.4.0 and no 1.3.X
series release will have them.

----------------------------------------------------------------

Changes since v1.3.0 are as follows:

Jonas Fonseca:
      Fix filename scaling for binary files

Junio C Hamano:
      git-merge: a bit more readable user guidance.
      pre-commit hook: complain about conflict markers.
      git-commit --amend: two fixes.
      pack-objects: do not stop at object that is "too small"
      mailinfo: decode underscore used in "Q" encoding properly.

Linus Torvalds:
      git-log produces no output

Nicolas Pitre:
      fix pack-object buffer size

Paul Mackerras:
      rev-parse: better error message for ambiguous arguments

Petr Baudis:
      Document git-var -l listing also configuration variables
      Document the configuration file

Santi Béjar:
      Reintroduce svn pools to solve the memory leak.

Serge E. Hallyn:
      socksetup: don't return on set_reuse_addr() error

Shawn Pearce:
      Document git-clone --reference

^ permalink raw reply

* Re: [RFC] get_sha1(): :path and :[0-3]:path to extract from index.
From: Uwe Zeisberger @ 2006-04-25  8:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7v7j5iph7f.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> [ NOTE! The reason I put "RFC" in the subject rather than "PATCH" is that 
>   I'm not 100% sure this isn't just a "shiny object" of mine rather than a 
>   really useful thing to do. What do people think? Have you ever wanted to 
>   access individual files in some random revision? Do you think this is 
>   useful? I think it's cool and _may_ be useful, but I'm not going to 
>   really push this patch. Consider it a throw-away patch unless somebody 
>   else finds it intriguing enough.. ]
> 
> This is a fairly straightforward patch to allow "get_sha1()" to
> also have shorthands for blob objects in the current index.
I sometimes want to have something like that:

	uzeisberger@io:~/gsrc/linux-2.6$ git cat-file blob v2.6.16:Makefile

That is not a shortcut for objects in the current index, but for blobs
in written trees.

It's easy to hack a script that does that.  Something like that[1]:


	#! /bin/sh

	eval `echo ${1} | sed 's/\\(.*\\):\\(.*\\)/commit=\"\\1^{}\"; file=\"\\2\"/'`

	tree=`git cat-file commit ${commit} | sed -n 's/tree //p'`

	blob=`git ls-tree -r ${tree} | awk "\\\$4 == \\"${file}\\" { print \\\$3 }"`

	git cat-file blob ${blob}


But if the rev-parser could handle that, that would be much finer.  Or
is there already a way to do this that I don't know?

Best regards
Uwe

[1] It's not tested and probably fails if there are some "bad"
characters in ${1} and could be implemented in a much cleverer way.

-- 
Uwe Zeisberger

http://www.google.com/search?q=0+degree+Celsius+in+kelvin

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: sean @ 2006-04-25  8:34 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <e2kjul$ntq$1@sea.gmane.org>

On Tue, 25 Apr 2006 09:43:33 +0200
Jakub Narebski <jnareb@gmail.com> wrote:

> Perhaps there should be an option to specify that the link is optional, and
> the object pointed can be gone missing. For example for cherrypick the
> original cherry-picked commit can either be removed completely, e.g. when
> the original branch is deleted, or it can be modified breaking link when we
> rewrite history up to original commit on original branch.
> 
> Also all other commands which show commit (commit messsage at least) should
> be considered for including "related" links...

If you're cherry-picking from a disposable branch, then you don't want to 
include a link to it in your new commit.  Once you include the link, the 
source commit should be protected from pruning just like any other piece 
of history.  Otherwise there's no way for fsck-objects to know if a missing 
object means corruption or not.  So you need a way at commit time to
request the explicit linkage.

This might be useful for bug tracking front ends that could automatically 
show a hot fix migrating from devel, to testing, to release branches.  With 
Junio's proposal, perhaps there's even a better keyword for these particular 
linkages.

Sean.

^ permalink raw reply

* Re: [PATCH 3/4] Deprecate usage of git-var -l for getting config vars list
From: Uwe Zeisberger @ 2006-04-25  8:39 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Junio C Hamano, git
In-Reply-To: <20060424225930.14086.76174.stgit@machine.or.cz>

Hello Petr,

Petr Baudis wrote:
> +    my @gitvars = `git-repo-config -l`;
>      if ($?) {
> -       print "E problems executing git-var on the server -- this is not a git repository or the PATH is not set correcly.\n";
> +       print "E problems executing git-repo-config on the server -- this is not a git repository or the PATH is not set correcly.\n";

I didn't check the patch, but you may want to s/correcly/correctly/.

Best regards
Uwe

-- 
Uwe Zeisberger

http://www.google.com/search?q=5+choose+3

^ permalink raw reply

* Re: [RFC] get_sha1(): :path and :[0-3]:path to extract from index.
From: Junio C Hamano @ 2006-04-25  8:46 UTC (permalink / raw)
  To: Uwe Zeisberger; +Cc: Linus Torvalds, git
In-Reply-To: <20060425083724.GA1663@informatik.uni-freiburg.de>

Uwe Zeisberger <zeisberg@informatik.uni-freiburg.de> writes:

>> This is a fairly straightforward patch to allow "get_sha1()" to
>> also have shorthands for blob objects in the current index.
>
> I sometimes want to have something like that:
>
> 	uzeisberger@io:~/gsrc/linux-2.6$ git cat-file blob v2.6.16:Makefile
>
> That is not a shortcut for objects in the current index, but for blobs
> in written trees.

That's already present in the "master".  You are responding to a
wrong message ;-).

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: sean @ 2006-04-25  8:57 UTC (permalink / raw)
  To: jnareb, git
In-Reply-To: <20060425043436.2ff53318.seanlkml@sympatico.ca>

On Tue, 25 Apr 2006 04:34:36 -0400
sean <seanlkml@sympatico.ca> wrote:

> If you're cherry-picking from a disposable branch, then you don't want to 
> include a link to it in your new commit.  Once you include the link, the 
> source commit should be protected from pruning just like any other piece 
> of history.  Otherwise there's no way for fsck-objects to know if a missing 
> object means corruption or not.  So you need a way at commit time to
> request the explicit linkage.

Actually this implies that anyone pulling just this branch would potentially
also end up pulling large portions of other branches too.   So maybe making
them optional is The Right Thing.  In which case, we'd just have to accept 
these as weaker than the parentage links and fsck-objects et. al. would have 
to tolerate such missing commits.

So now that i've clearly come down in favor of both sides of this argument,
i'll leave the decision to smarter people than me.

Sean

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Jakub Narebski @ 2006-04-25  9:10 UTC (permalink / raw)
  To: git
In-Reply-To: <BAYC1-PASMTP116C6B217F25F2ADAF0C67AEBF0@CEZ.ICE>

sean wrote:

> On Tue, 25 Apr 2006 04:34:36 -0400
> sean <seanlkml@sympatico.ca> wrote:
> 
>> If you're cherry-picking from a disposable branch, then you don't want to
>> include a link to it in your new commit.  Once you include the link, the
>> source commit should be protected from pruning just like any other piece
>> of history.  Otherwise there's no way for fsck-objects to know if a
>> missing
>> object means corruption or not.  So you need a way at commit time to
>> request the explicit linkage.
> 
> Actually this implies that anyone pulling just this branch would
> potentially
> also end up pulling large portions of other branches too.   So maybe
> making
> them optional is The Right Thing.  In which case, we'd just have to accept
> these as weaker than the parentage links and fsck-objects et. al. would
> have to tolerate such missing commits.

Actually, this can be resolved using automatic history grafts to the remote
repository we pulled from, if the commit is not present on local side (and
removing graft when commit appears on local side).

I was more concerned about size of repository required by keeping some parts
of history which would be purged without those "related" links. But your
concern (pulling) is more important.

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Junio C Hamano @ 2006-04-25  9:58 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: jnareb, git
In-Reply-To: <e2kp27$8ne$1@sea.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> Actually, this can be resolved using automatic history grafts to the remote
> repository we pulled from, if the commit is not present on local side (and
> removing graft when commit appears on local side).

You do not even need history grafts.  The "cherry-pick source"
was a bad example.  Maybe using "related" as a way to implement
"bind" would have been a better example -- we want inter-commit
relationship that requires connectivity but without ancestry for
them.

You can just have two kinds of 'related'.  One that means
connectivity, the other that does not.

At that point, the latter does not even have to belong to the
core.  The Porcelains can make use of it as long as they agree
on a common convention and use that information consistently.
It does not even have to be "related" (which implies what comes
after "related" is an object name) -- it could be an arbitrary
metainformation that the core does not have to care.  So an
updated suggestion is to have optional 0-or-more "note" and
"related" fields.  'note' is followed by one token and
additional information.  'related' is followed by an object name
that needs the additional connectivity, and and additional
information.  For example:

    tree 0aaa3fecff73ab428999cb9156f8abc075516abe
    parent 5a6a8c0e012137a3f0059be40ec7b2f4aa614355
    parent e1cbc46d12a0524fd5e710cbfaf3f178fc3da504
    related a0e7d36193b96f552073558acf5fcc1f10528917 bind linux-2.6
    note cherrypick v1.3.0~12
    note origin "next" branch at junio's repository
    note rename "foobar" to "barboz"
    author Junio C Hamano <junkio@cox.net> 1145943079 -0700
    committer Junio C Hamano <junkio@cox.net> 1145943079 -0700

    Merge branch 'pb/config' into next

The core side can say "Oh, this is a 'note' so I do not care
what it is -- I'd just skip to the end of line", while
Porcelains that "cat-file commit" this object can grep for
"note" and look at the first token to figure out what to do with
it.  The core needs to be aware of the 'related' ones and does
the connectivity crud using the object name, and Porcelains can
use the rest of the line to do intelligent things.

Now, it is debatable that such an extra information like 'note'
belongs to the header that the core deals with.  IIRC, Linus
argued that he does not want to have arbitrary cruft in the
header and instead to have it as a comment in the message part
when somebody talked about recording renames in the commit.

We have the author and the committer fields that is not used by
the core (only half of the committer field is used by the core
to date-order the commit list).  But I suspect most of the time
such metainformation is useless to the end-user humans, so if I
have to vote I'd rather put them in the header, have the UI
layer filter them out unless asked when presenting the commit to
the humans, and give Porcelains freedom to do whatever they
wish.

Things are easier to filter out when they properly follow some
structure, so I'd rather have "cruft" in the header.  Right now,
git-cherry-pick ends the commit message with "(cherry picked
from $commit commit)".  In theory, rebase can notice by parsing
commit log message, but it certainly would be easier and more
robust if we had a 'note' facility and a well established
convention to use it.

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Jakub Narebski @ 2006-04-25 10:08 UTC (permalink / raw)
  To: git
In-Reply-To: <7vmzeax9gj.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:

> Jakub Narebski <jnareb@gmail.com> writes:
> 
>> Actually, this can be resolved using automatic history grafts to the
>> remote repository we pulled from, if the commit is not present on local
>> side (and removing graft when commit appears on local side).
> 
> You do not even need history grafts.  The "cherry-pick source"
> was a bad example.  Maybe using "related" as a way to implement
> "bind" would have been a better example -- we want inter-commit
> relationship that requires connectivity but without ancestry for
> them.
> 
> You can just have two kinds of 'related'.  One that means
> connectivity, the other that does not.

Good idea.

Another problem for core git, but I think orthogonal to the "related"/"note"
distinction is if the relation (or note) should be used as helper in
merges, perhaps by some agreed upon convention on the
comment/description/value part (e.g. "mergehelper" or "mergeinfo").

BTW. in your first example, what "key" relation should mean?
"cherrypick" (which should be "note" as we don't need connectivity) is
quite obvious (or equivalent "origin" if rebase wouldn't destroy the branch
picked from).

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* [PATCH] Make die() and error() prefix line with binary name if set
From: Rocco Rutte @ 2006-04-25 10:12 UTC (permalink / raw)
  To: git

Since lots of logic is implemented via shell scripts, it's in
general useful to print out where an error occured. Previously
only some commands manually added the binary name to die() and
error() calls.

Now, git_set_appname() can be used to set the name of the binary
as first call in a binary's main() routine which will be used
as prefix in die() and error(). If it was not called, no prefix
will be printed.

Signed-off-by: Rocco Rutte <pdmef@gmx.net>

---

  apply.c              |   10 ++++++----
  blame.c              |    2 ++
  cat-file.c           |   10 ++++++----
  check-ref-format.c   |    2 ++
  checkout-index.c     |    8 +++++---
  clone-pack.c         |    2 ++
  commit-tree.c        |    2 ++
  connect.c            |    4 ++--
  convert-objects.c    |    2 ++
  daemon.c             |    4 +++-
  describe.c           |    2 ++
  diff-files.c         |    5 ++++-
  diff-index.c         |    5 ++++-
  diff-stages.c        |    5 ++++-
  diff-tree.c          |    2 ++
  entry.c              |   14 +++++++-------
  fetch-clone.c        |    2 +-
  fetch-pack.c         |    4 +++-
  fsck-objects.c       |    2 ++
  get-tar-commit-id.c  |    2 ++
  git-compat-util.h    |    1 +
  git.c                |    2 ++
  hash-object.c        |    2 ++
  http-fetch.c         |    2 ++
  http-push.c          |    2 ++
  index-pack.c         |    2 ++
  init-db.c            |    2 ++
  local-fetch.c        |    2 ++
  ls-files.c           |    8 +++++---
  ls-tree.c            |    2 ++
  mailinfo.c           |    2 ++
  mailsplit.c          |    2 ++
  merge-base.c         |    2 ++
  merge-index.c        |    8 +++++---
  merge-tree.c         |    2 ++
  mktag.c              |    2 ++
  mktree.c             |    2 ++
  name-rev.c           |    2 ++
  pack-objects.c       |    2 ++
  pack-redundant.c     |    2 ++
  patch-id.c           |    2 ++
  peek-remote.c        |    2 ++
  prune-packed.c       |    2 ++
  read-tree.c          |    2 ++
  receive-pack.c       |    2 ++
  repo-config.c        |    2 ++
  rev-list.c           |    2 ++
  rev-parse.c          |    5 ++++-
  send-pack.c          |    2 ++
  shell.c              |    2 ++
  show-branch.c        |    2 ++
  show-index.c         |    2 ++
  ssh-fetch.c          |    2 ++
  ssh-upload.c         |    2 ++
  stripspace.c         |    2 ++
  symbolic-ref.c       |    2 ++
  tar-tree.c           |    6 ++++--
  test-date.c          |    2 ++
  test-delta.c         |    2 ++
  tree-diff.c          |    2 +-
  unpack-file.c        |    2 ++
  unpack-objects.c     |    2 ++
  update-index.c       |   23 ++++++++++++++---------
  update-ref.c         |    2 ++
  update-server-info.c |    3 +++
  upload-pack.c        |   20 +++++++++++---------
  usage.c              |   14 ++++++++++++++
  var.c                |    3 +++
  verify-pack.c        |    2 ++
  write-tree.c         |   10 ++++++----
  70 files changed, 210 insertions(+), 58 deletions(-)

92e903a0273996028d069b28fde6c5a990e1157b
diff --git a/apply.c b/apply.c
index 269210a..84879d2 100644
--- a/apply.c
+++ b/apply.c
@@ -142,7 +142,7 @@ static void *read_patch_file(int fd, uns
  		if (!nr)
  			break;
  		if (nr < 0)
-			die("git-apply: read returned %s", strerror(errno));
+			die("read returned %s", strerror(errno));
  		size += nr;
  	}
  	*sizep = size;
@@ -320,17 +320,17 @@ static char *gitdiff_verify_name(const c
  		name = orig_name;
  		len = strlen(name);
  		if (isnull)
-			die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
+			die("bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
  		another = find_name(line, NULL, 1, 0);
  		if (!another || memcmp(another, name, len))
-			die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
+			die("bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
  		free(another);
  		return orig_name;
  	}
  	else {
  		/* expect "/dev/null" */
  		if (memcmp("/dev/null", line, 9) || line[9] != '\n')
-			die("git-apply: bad git-diff - expected /dev/null on line %d", linenr);
+			die("bad git-diff - expected /dev/null on line %d", linenr);
  		return NULL;
  	}
  }
@@ -1960,6 +1960,8 @@ int main(int argc, char **argv)
  	int read_stdin = 1;
  	const char *whitespace_option = NULL;
  
+	git_set_appname("git-apply");
+
  	for (i = 1; i < argc; i++) {
  		const char *arg = argv[i];
  		char *end;
diff --git a/blame.c b/blame.c
index 07d2d27..804f108 100644
--- a/blame.c
+++ b/blame.c
@@ -752,6 +752,8 @@ int main(int argc, const char **argv)
  	int longest_file, longest_author;
  	int found_rename;
  
+	git_set_appname("git-blame");
+
  	const char* prefix = setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/cat-file.c b/cat-file.c
index 628f6ca..75c400a 100644
--- a/cat-file.c
+++ b/cat-file.c
@@ -16,9 +16,9 @@ static void flush_buffer(const char *buf
  			/* Ignore epipe */
  			if (errno == EPIPE)
  				break;
-			die("git-cat-file: %s", strerror(errno));
+			die("%s", strerror(errno));
  		} else if (!ret) {
-			die("git-cat-file: disk full?");
+			die("disk full?");
  		}
  		size -= ret;
  		buf += ret;
@@ -101,6 +101,8 @@ int main(int argc, char **argv)
  	unsigned long size;
  	int opt;
  
+	git_set_appname("git-cat-file");
+
  	setup_git_directory();
  	git_config(git_default_config);
  	if (argc != 3 || get_sha1(argv[2], sha1))
@@ -154,11 +156,11 @@ int main(int argc, char **argv)
  		break;
  
  	default:
-		die("git-cat-file: unknown option: %s\n", argv[1]);
+		die("unknown option: %s\n", argv[1]);
  	}
  
  	if (!buf)
-		die("git-cat-file %s: bad file", argv[2]);
+		die("bad file", argv[2]);
  
  	flush_buffer(buf, size);
  	return 0;
diff --git a/check-ref-format.c b/check-ref-format.c
index a0adb3d..ce08eda 100644
--- a/check-ref-format.c
+++ b/check-ref-format.c
@@ -9,6 +9,8 @@ #include <stdio.h>
  
  int main(int ac, char **av)
  {
+	git_set_appname("git-check-ref-format");
+
  	if (ac != 2)
  		usage("git-check-ref-format refname");
  	if (check_ref_format(av[1]))
diff --git a/checkout-index.c b/checkout-index.c
index dd6a2d8..b515651 100644
--- a/checkout-index.c
+++ b/checkout-index.c
@@ -176,6 +176,8 @@ int main(int argc, char **argv)
  	int all = 0;
  	int read_from_stdin = 0;
  
+	git_set_appname("git-checkout-index");
+
  	prefix = setup_git_directory();
  	git_config(git_default_config);
  	prefix_length = prefix ? strlen(prefix) : 0;
@@ -271,16 +273,16 @@ int main(int argc, char **argv)
  		const char *arg = argv[i];
  
  		if (all)
-			die("git-checkout-index: don't mix '--all' and explicit filenames");
+			die("don't mix '--all' and explicit filenames");
  		if (read_from_stdin)
-			die("git-checkout-index: don't mix '--stdin' and explicit filenames");
+			die("don't mix '--stdin' and explicit filenames");
  		checkout_file(prefix_path(prefix, prefix_length, arg));
  	}
  
  	if (read_from_stdin) {
  		struct strbuf buf;
  		if (all)
-			die("git-checkout-index: don't mix '--all' and '--stdin'");
+			die("don't mix '--all' and '--stdin'");
  		strbuf_init(&buf);
  		while (1) {
  			char *path_name;
diff --git a/clone-pack.c b/clone-pack.c
index a4370f5..0139745 100644
--- a/clone-pack.c
+++ b/clone-pack.c
@@ -150,6 +150,8 @@ int main(int argc, char **argv)
  	int fd[2];
  	pid_t pid;
  
+	git_set_appname("git-clone-pack");
+
  	setup_git_directory();
  
  	nr_heads = 0;
diff --git a/commit-tree.c b/commit-tree.c
index 2d86518..e07b0eb 100644
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -87,6 +87,8 @@ int main(int argc, char **argv)
  	char *buffer;
  	unsigned int size;
  
+	git_set_appname("git-commit-tree");
+
  	setup_ident();
  	setup_git_directory();
  
diff --git a/connect.c b/connect.c
index 6a8f8a6..70ab5ad 100644
--- a/connect.c
+++ b/connect.c
@@ -69,7 +69,7 @@ int get_ack(int fd, unsigned char *resul
  	int len = packet_read_line(fd, line, sizeof(line));
  
  	if (!len)
-		die("git-fetch-pack: expected ACK/NAK, got EOF");
+		die("expected ACK/NAK, got EOF");
  	if (line[len-1] == '\n')
  		line[--len] = 0;
  	if (!strcmp(line, "NAK"))
@@ -81,7 +81,7 @@ int get_ack(int fd, unsigned char *resul
  			return 1;
  		}
  	}
-	die("git-fetch_pack: expected ACK/NAK, got '%s'", line);
+	die("expected ACK/NAK, got '%s'", line);
  }
  
  int path_match(const char *path, int nr, char **match)
diff --git a/convert-objects.c b/convert-objects.c
index 12aacef..6b5d955 100644
--- a/convert-objects.c
+++ b/convert-objects.c
@@ -319,6 +319,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20];
  	struct entry *entry;
  
+	git_set_appname("git-convert-object");
+
  	setup_git_directory();
  
  	if (argc != 2 || get_sha1(argv[1], sha1))
diff --git a/daemon.c b/daemon.c
index a1ccda3..ddf59d0 100644
--- a/daemon.c
+++ b/daemon.c
@@ -666,6 +666,8 @@ int main(int argc, char **argv)
  	int inetd_mode = 0;
  	int i;
  
+	git_set_appname("git-daemon");
+
  	for (i = 1; i < argc; i++) {
  		char *arg = argv[i];
  
@@ -739,7 +741,7 @@ int main(int argc, char **argv)
  
  	if (strict_paths && (!ok_paths || !*ok_paths)) {
  		if (!inetd_mode)
-			die("git-daemon: option --strict-paths requires a whitelist");
+			die("option --strict-paths requires a whitelist");
  
  		logerror("option --strict-paths requires a whitelist");
  		exit (1);
diff --git a/describe.c b/describe.c
index ff65742..a882d00 100644
--- a/describe.c
+++ b/describe.c
@@ -143,6 +143,8 @@ int main(int argc, char **argv)
  {
  	int i;
  
+	git_set_appname("git-describe");
+
  	for (i = 1; i < argc; i++) {
  		const char *arg = argv[i];
  
diff --git a/diff-files.c b/diff-files.c
index ffbef48..0c99c00 100644
--- a/diff-files.c
+++ b/diff-files.c
@@ -39,9 +39,12 @@ static void show_modified(int oldmode, i
  int main(int argc, const char **argv)
  {
  	const char **pathspec;
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	int entries, i;
  
+	git_set_appname("git-diff-files");
+
+	prefix = setup_git_directory();
  	git_config(git_diff_config);
  	diff_setup(&rev.diffopt);
  	while (1 < argc && argv[1][0] == '-') {
diff --git a/diff-index.c b/diff-index.c
index e376d65..b066d48 100644
--- a/diff-index.c
+++ b/diff-index.c
@@ -171,13 +171,16 @@ int main(int argc, const char **argv)
  {
  	const char *tree_name = NULL;
  	unsigned char sha1[20];
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	const char **pathspec = NULL;
  	struct tree *tree;
  	int ret;
  	int allow_options = 1;
  	int i;
  
+	git_set_appname("git-diff-index");
+
+	prefix = setup_git_directory();
  	git_config(git_diff_config);
  	diff_setup(&diff_options);
  	for (i = 1; i < argc; i++) {
diff --git a/diff-stages.c b/diff-stages.c
index dcd20e7..bd40b8e 100644
--- a/diff-stages.c
+++ b/diff-stages.c
@@ -57,9 +57,12 @@ static void diff_stages(int stage1, int 
  int main(int ac, const char **av)
  {
  	int stage1, stage2;
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	const char **pathspec = NULL;
  
+	git_set_appname("git-diff-stages");
+
+	prefix = setup_git_directory();
  	git_config(git_diff_config);
  	read_cache();
  	diff_setup(&diff_options);
diff --git a/diff-tree.c b/diff-tree.c
index 7207867..76222d5 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -67,6 +67,8 @@ int main(int argc, const char **argv)
  	struct object_list *list;
  	int read_stdin = 0;
  
+	git_set_appname("git-diff-tree");
+
  	git_config(git_diff_config);
  	nr_sha1 = 0;
  	init_revisions(opt);
diff --git a/entry.c b/entry.c
index 793724f..5cf36f9 100644
--- a/entry.c
+++ b/entry.c
@@ -76,7 +76,7 @@ static int write_entry(struct cache_entr
  	if (!new || strcmp(type, blob_type)) {
  		if (new)
  			free(new);
-		return error("git-checkout-index: unable to read sha1 file of %s (%s)",
+		return error("unable to read sha1 file of %s (%s)",
  			path, sha1_to_hex(ce->sha1));
  	}
  	switch (ntohl(ce->ce_mode) & S_IFMT) {
@@ -88,14 +88,14 @@ static int write_entry(struct cache_entr
  			fd = create_file(path, ntohl(ce->ce_mode));
  		if (fd < 0) {
  			free(new);
-			return error("git-checkout-index: unable to create file %s (%s)",
+			return error("unable to create file %s (%s)",
  				path, strerror(errno));
  		}
  		wrote = write(fd, new, size);
  		close(fd);
  		free(new);
  		if (wrote != size)
-			return error("git-checkout-index: unable to write file %s", path);
+			return error("unable to write file %s", path);
  		break;
  	case S_IFLNK:
  		if (to_tempfile) {
@@ -103,26 +103,26 @@ static int write_entry(struct cache_entr
  			fd = mkstemp(path);
  			if (fd < 0) {
  				free(new);
-				return error("git-checkout-index: unable to create "
+				return error("unable to create "
  						 "file %s (%s)", path, strerror(errno));
  			}
  			wrote = write(fd, new, size);
  			close(fd);
  			free(new);
  			if (wrote != size)
-				return error("git-checkout-index: unable to write file %s",
+				return error("unable to write file %s",
  					path);
  		} else {
  			wrote = symlink(new, path);
  			free(new);
  			if (wrote)
-				return error("git-checkout-index: unable to create "
+				return error("unable to create "
  						 "symlink %s (%s)", path, strerror(errno));
  		}
  		break;
  	default:
  		free(new);
-		return error("git-checkout-index: unknown file mode for %s", path);
+		return error("unknown file mode for %s", path);
  	}
  
  	if (state->refresh_cache) {
diff --git a/fetch-clone.c b/fetch-clone.c
index da1b3ff..b44ab8f 100644
--- a/fetch-clone.c
+++ b/fetch-clone.c
@@ -23,7 +23,7 @@ static int finish_pack(const char *pack_
  
  	pid = fork();
  	if (pid < 0)
-		die("git-clone-pack: unable to fork off git-index-pack");
+		die("unable to fork off git-index-pack");
  	if (!pid) {
  		close(0);
  		dup2(pipe_fd[1], 1);
diff --git a/fetch-pack.c b/fetch-pack.c
index a3bcad0..f7053e7 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -390,7 +390,7 @@ static int fetch_pack(int fd[2], int nr_
  		status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
  
  	if (status)
-		die("git-fetch-pack: fetch failed.");
+		die("fetch failed.");
  
   all_done:
  	while (ref) {
@@ -408,6 +408,8 @@ int main(int argc, char **argv)
  	int fd[2];
  	pid_t pid;
  
+	git_set_appname("git-fetch-pack");
+
  	setup_git_directory();
  
  	nr_heads = 0;
diff --git a/fsck-objects.c b/fsck-objects.c
index 59b2590..5e004b6 100644
--- a/fsck-objects.c
+++ b/fsck-objects.c
@@ -442,6 +442,8 @@ int main(int argc, char **argv)
  {
  	int i, heads;
  
+	git_set_appname("git-fsck-objects");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/get-tar-commit-id.c b/get-tar-commit-id.c
index 4166290..036094d 100644
--- a/get-tar-commit-id.c
+++ b/get-tar-commit-id.c
@@ -12,6 +12,8 @@ int main(int argc, char **argv)
  	char buffer[HEADERSIZE];
  	ssize_t n;
  
+	git_set_appname("git-get-tar-commit-id");
+
  	n = read(0, buffer, HEADERSIZE);
  	if (n < HEADERSIZE) {
  		fprintf(stderr, "read error\n");
diff --git a/git-compat-util.h b/git-compat-util.h
index 5d543d2..cc5370c 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -39,6 +39,7 @@ #endif
  extern void usage(const char *err) NORETURN;
  extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
  extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void git_set_appname(const char *name);
  
  #ifdef NO_MMAP
  
diff --git a/git.c b/git.c
index aa2b814..ad49bb7 100644
--- a/git.c
+++ b/git.c
@@ -71,6 +71,8 @@ int main(int argc, const char **argv, ch
  	char git_command[PATH_MAX + 1];
  	const char *exec_path = NULL;
  
+	git_set_appname("git");
+
  	/*
  	 * Take the basename of argv[0] as the command
  	 * name, and the dirname as the default exec_path
diff --git a/hash-object.c b/hash-object.c
index 43bd93b..0c95d05 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -42,6 +42,8 @@ int main(int argc, char **argv)
  	int prefix_length = -1;
  	int no_more_flags = 0;
  
+	git_set_appname("git-hash-object");
+
  	for (i = 1 ; i < argc; i++) {
  		if (!no_more_flags && argv[i][0] == '-') {
  			if (!strcmp(argv[i], "-t")) {
diff --git a/http-fetch.c b/http-fetch.c
index 861644b..69c7cdb 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -1222,6 +1222,8 @@ int main(int argc, char **argv)
  	int arg = 1;
  	int rc = 0;
  
+	git_set_appname("git-http-fetch");
+
  	setup_git_directory();
  
  	while (arg < argc && argv[arg][0] == '-') {
diff --git a/http-push.c b/http-push.c
index b4327d9..75a544b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -2315,6 +2315,8 @@ int main(int argc, char **argv)
  	int new_refs;
  	struct ref *ref;
  
+	git_set_appname("git-http-push");
+
  	setup_git_directory();
  	setup_ident();
  
diff --git a/index-pack.c b/index-pack.c
index b39953d..a69e51a 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -425,6 +425,8 @@ int main(int argc, char **argv)
  	char *index_name_buf = NULL;
  	unsigned char sha1[20];
  
+	git_set_appname("git-index-pack");
+
  	for (i = 1; i < argc; i++) {
  		const char *arg = argv[i];
  
diff --git a/init-db.c b/init-db.c
index ff29496..29c93e3 100644
--- a/init-db.c
+++ b/init-db.c
@@ -241,6 +241,8 @@ int main(int argc, char **argv)
  	char *path, *template_dir = NULL;
  	int len, i;
  
+	git_set_appname("git-init-db");
+
  	for (i = 1; i < argc; i++, argv++) {
  		char *arg = argv[1];
  		if (!strncmp(arg, "--template=", 11))
diff --git a/local-fetch.c b/local-fetch.c
index fa9e697..11bf6f8 100644
--- a/local-fetch.c
+++ b/local-fetch.c
@@ -207,6 +207,8 @@ int main(int argc, char **argv)
  	char *commit_id;
  	int arg = 1;
  
+	git_set_appname("git-local-fetch");
+
  	setup_git_directory();
  
  	while (arg < argc && argv[arg][0] == '-') {
diff --git a/ls-files.c b/ls-files.c
index 4a4af1c..15a9bb2 100644
--- a/ls-files.c
+++ b/ls-files.c
@@ -383,7 +383,7 @@ static void show_dir_entry(const char *t
  	int offset = prefix_offset;
  
  	if (len >= ent->len)
-		die("git-ls-files: internal error - directory entry not superset of prefix");
+		die("internal error - directory entry not superset of prefix");
  
  	if (pathspec && !match(pathspec, ps_matched, ent->name, len))
  		return;
@@ -471,7 +471,7 @@ static void show_ce_entry(const char *ta
  	int offset = prefix_offset;
  
  	if (len >= ce_namelen(ce))
-		die("git-ls-files: internal error - cache entry not superset of prefix");
+		die("internal error - cache entry not superset of prefix");
  
  	if (pathspec && !match(pathspec, ps_matched, ce->name, len))
  		return;
@@ -630,7 +630,7 @@ static void verify_pathspec(void)
  	}
  
  	if (prefix_offset > max || memcmp(prev, prefix, prefix_offset))
-		die("git-ls-files: cannot generate relative filenames containing '..'");
+		die("cannot generate relative filenames containing '..'");
  
  	real_prefix = NULL;
  	prefix_len = max;
@@ -653,6 +653,8 @@ int main(int argc, const char **argv)
  	int i;
  	int exc_given = 0;
  
+	git_set_appname("git-ls-files");
+
  	prefix = setup_git_directory();
  	if (prefix)
  		prefix_offset = strlen(prefix);
diff --git a/ls-tree.c b/ls-tree.c
index e4ef200..e037bf0 100644
--- a/ls-tree.c
+++ b/ls-tree.c
@@ -89,6 +89,8 @@ int main(int argc, const char **argv)
  	unsigned char sha1[20];
  	struct tree *tree;
  
+	git_set_appname("git-ls-tree");
+
  	prefix = setup_git_directory();
  	git_config(git_default_config);
  	if (prefix && *prefix)
diff --git a/mailinfo.c b/mailinfo.c
index b276519..7baa3ff 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -757,6 +757,8 @@ static const char mailinfo_usage[] =
  
  int main(int argc, char **argv)
  {
+	git_set_appname("git-mailinfo");
+
  	/* NEEDSWORK: might want to do the optional .git/ directory
  	 * discovery
  	 */
diff --git a/mailsplit.c b/mailsplit.c
index c529e2d..686920e 100644
--- a/mailsplit.c
+++ b/mailsplit.c
@@ -111,6 +111,8 @@ int main(int argc, const char **argv)
  	static const char *stdin_only[] = { "-", NULL };
  	char *name;
  
+	git_set_appname("git-mailsplit");
+
  	for (argp = argv+1; *argp; argp++) {
  		const char *arg = *argp;
  
diff --git a/merge-base.c b/merge-base.c
index 07f5ab4..29cdbd7 100644
--- a/merge-base.c
+++ b/merge-base.c
@@ -236,6 +236,8 @@ int main(int argc, char **argv)
  	struct commit *rev1, *rev2;
  	unsigned char rev1key[20], rev2key[20];
  
+	git_set_appname("git-merge-base");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/merge-index.c b/merge-index.c
index 024196e..3430da5 100644
--- a/merge-index.c
+++ b/merge-index.c
@@ -42,7 +42,7 @@ static int merge_entry(int pos, const ch
  	int found;
  	
  	if (pos >= active_nr)
-		die("git-merge-index: %s not in the cache", path);
+		die("%s not in the cache", path);
  	arguments[0] = pgm;
  	arguments[1] = "";
  	arguments[2] = "";
@@ -67,7 +67,7 @@ static int merge_entry(int pos, const ch
  		arguments[stage + 4] = ownbuf[stage];
  	} while (++pos < active_nr);
  	if (!found)
-		die("git-merge-index: %s not in the cache", path);
+		die("%s not in the cache", path);
  	run_program();
  	return found;
  }
@@ -99,6 +99,8 @@ int main(int argc, char **argv)
  {
  	int i, force_file = 0;
  
+	git_set_appname("git-merge-index");
+
  	if (argc < 3)
  		usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
  
@@ -126,7 +128,7 @@ int main(int argc, char **argv)
  				merge_all();
  				continue;
  			}
-			die("git-merge-index: unknown option %s", arg);
+			die("unknown option %s", arg);
  		}
  		merge_file(arg);
  	}
diff --git a/merge-tree.c b/merge-tree.c
index 50528d5..1eca1d7 100644
--- a/merge-tree.c
+++ b/merge-tree.c
@@ -164,6 +164,8 @@ int main(int argc, char **argv)
  	struct tree_desc t[3];
  	void *buf1, *buf2, *buf3;
  
+	git_set_appname("git-merge-tree");
+
  	if (argc < 4)
  		usage(merge_tree_usage);
  
diff --git a/mktag.c b/mktag.c
index 2328878..dcc917e 100644
--- a/mktag.c
+++ b/mktag.c
@@ -109,6 +109,8 @@ int main(int argc, char **argv)
  	char buffer[MAXSIZE];
  	unsigned char result_sha1[20];
  
+	git_set_appname("git-mktag");
+
  	if (argc != 1)
  		usage("cat <signaturefile> | git-mktag");
  
diff --git a/mktree.c b/mktree.c
index ab63cd9..a1ac929 100644
--- a/mktree.c
+++ b/mktree.c
@@ -79,6 +79,8 @@ int main(int ac, char **av)
  	unsigned char sha1[20];
  	int line_termination = '\n';
  
+	git_set_appname("git-mktree");
+
  	setup_git_directory();
  
  	while ((1 < ac) && av[1][0] == '-') {
diff --git a/name-rev.c b/name-rev.c
index bad8a53..c426059 100644
--- a/name-rev.c
+++ b/name-rev.c
@@ -126,6 +126,8 @@ int main(int argc, char **argv)
  	struct object_list **walker = &revs;
  	int as_is = 0, all = 0, transform_stdin = 0;
  
+	git_set_appname("git-name-rev");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/pack-objects.c b/pack-objects.c
index c0acc46..de733b6 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -1237,6 +1237,8 @@ int main(int argc, char **argv)
  	int num_preferred_base = 0;
  	int i;
  
+	git_set_appname("git-pack-objects");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/pack-redundant.c b/pack-redundant.c
index cd81f5a..e2eff1b 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -589,6 +589,8 @@ int main(int argc, char **argv)
  	unsigned char *sha1;
  	char buf[42]; /* 40 byte sha1 + \n + \0 */
  
+	git_set_appname("git-pack-redundant");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/patch-id.c b/patch-id.c
index edbc4aa..0e2bd85 100644
--- a/patch-id.c
+++ b/patch-id.c
@@ -74,6 +74,8 @@ static const char patch_id_usage[] = "gi
  
  int main(int argc, char **argv)
  {
+	git_set_appname("git-patch-id");
+
  	if (argc != 1)
  		usage(patch_id_usage);
  
diff --git a/peek-remote.c b/peek-remote.c
index a90cf22..99dac1b 100644
--- a/peek-remote.c
+++ b/peek-remote.c
@@ -29,6 +29,8 @@ int main(int argc, char **argv)
  	pid_t pid;
  	int nongit = 0;
  
+	git_set_appname("git-pack-remote");
+
  	setup_git_directory_gently(&nongit);
  
  	for (i = 1; i < argc; i++) {
diff --git a/prune-packed.c b/prune-packed.c
index d24b097..106cc39 100644
--- a/prune-packed.c
+++ b/prune-packed.c
@@ -58,6 +58,8 @@ int main(int argc, char **argv)
  {
  	int i;
  
+	git_set_appname("git-prune-packed");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/read-tree.c b/read-tree.c
index 26f4f7e..23c2014 100644
--- a/read-tree.c
+++ b/read-tree.c
@@ -723,6 +723,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20];
  	merge_fn_t fn = NULL;
  
+	git_set_appname("git-read-tree");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/receive-pack.c b/receive-pack.c
index 93929b5..8ad291c 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -304,6 +304,8 @@ int main(int argc, char **argv)
  	int i;
  	char *dir = NULL;
  
+	git_set_appname("git-receive-pack");
+
  	argv++;
  	for (i = 1; i < argc; i++) {
  		char *arg = *argv++;
diff --git a/repo-config.c b/repo-config.c
index c5ebb76..793af68 100644
--- a/repo-config.c
+++ b/repo-config.c
@@ -86,6 +86,8 @@ static int get_value(const char* key_, c
  
  int main(int argc, const char **argv)
  {
+	git_set_appname("git-repo-config");
+
  	setup_git_directory();
  
  	while (1 < argc) {
diff --git a/rev-list.c b/rev-list.c
index 8b0ec38..4646372 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -296,6 +296,8 @@ int main(int argc, const char **argv)
  	struct commit_list *list;
  	int i;
  
+	git_set_appname("git-rev-list");
+
  	init_revisions(&revs);
  	revs.abbrev = 0;
  	revs.commit_format = CMIT_FMT_UNSPECIFIED;
diff --git a/rev-parse.c b/rev-parse.c
index e956cd5..b0b701e 100644
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -164,8 +164,11 @@ int main(int argc, char **argv)
  {
  	int i, as_is = 0, verify = 0;
  	unsigned char sha1[20];
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	
+	git_set_appname("git-rev-parse");
+
+	prefix = setup_git_directory();
  	git_config(git_default_config);
  
  	for (i = 1; i < argc; i++) {
diff --git a/send-pack.c b/send-pack.c
index 409f188..803e193 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -361,6 +361,8 @@ int main(int argc, char **argv)
  	int fd[2], ret;
  	pid_t pid;
  
+	git_set_appname("git-send-pack");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/shell.c b/shell.c
index 8c08cf0..c22cde1 100644
--- a/shell.c
+++ b/shell.c
@@ -32,6 +32,8 @@ int main(int argc, char **argv)
  	char *prog;
  	struct commands *cmd;
  
+	git_set_appname("git-shell");
+
  	/* We want to see "-c cmd args", and nothing else */
  	if (argc != 3 || strcmp(argv[1], "-c"))
  		die("What do you think I am? A shell?");
diff --git a/show-branch.c b/show-branch.c
index 24efb65..9ec3553 100644
--- a/show-branch.c
+++ b/show-branch.c
@@ -549,6 +549,8 @@ int main(int ac, char **av)
  	int head_at = -1;
  	int topics = 0;
  
+	git_set_appname("git-show-branch");
+
  	setup_git_directory();
  	git_config(git_show_branch_config);
  
diff --git a/show-index.c b/show-index.c
index c21d660..b8a9fba 100644
--- a/show-index.c
+++ b/show-index.c
@@ -7,6 +7,8 @@ int main(int argc, char **argv)
  	unsigned int entry[6];
  	static unsigned int top_index[256];
  
+	git_set_appname("git-show-index");
+
  	if (fread(top_index, sizeof(top_index), 1, stdin) != 1)
  		die("unable to read idex");
  	nr = 0;
diff --git a/ssh-fetch.c b/ssh-fetch.c
index 4eb9e04..4bab7e7 100644
--- a/ssh-fetch.c
+++ b/ssh-fetch.c
@@ -128,6 +128,8 @@ int main(int argc, char **argv)
  	int arg = 1;
  	const char *prog;
  
+	git_set_appname("git-ssh-fetch");
+
  	prog = getenv("GIT_SSH_PUSH");
  	if (!prog) prog = "git-ssh-upload";
  
diff --git a/ssh-upload.c b/ssh-upload.c
index b675a0b..9860cf4 100644
--- a/ssh-upload.c
+++ b/ssh-upload.c
@@ -119,6 +119,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20];
  	char hex[41];
  
+	git_set_appname("git-ssh-upload");
+
  	prog = getenv(COUNTERPART_ENV_NAME);
  	if (!prog) prog = COUNTERPART_PROGRAM_NAME;
  
diff --git a/stripspace.c b/stripspace.c
index 65a6346..95c2e43 100644
--- a/stripspace.c
+++ b/stripspace.c
@@ -34,6 +34,8 @@ int main(int argc, char **argv)
  	int incomplete = 0;
  	char line[1024];
  
+	git_set_appname("git-stripspace");
+
  	while (fgets(line, sizeof(line), stdin)) {
  		incomplete = cleanup(line);
  
diff --git a/symbolic-ref.c b/symbolic-ref.c
index 193c87c..a8b3b9d 100644
--- a/symbolic-ref.c
+++ b/symbolic-ref.c
@@ -19,6 +19,8 @@ static void check_symref(const char *HEA
  
  int main(int argc, const char **argv)
  {
+	git_set_appname("git-symbolic-ref");
+
  	setup_git_directory();
  	git_config(git_default_config);
  	switch (argc) {
diff --git a/tar-tree.c b/tar-tree.c
index fc60a90..7a388f5 100644
--- a/tar-tree.c
+++ b/tar-tree.c
@@ -26,9 +26,9 @@ static void reliable_write(void *buf, un
  		if (ret < 0) {
  			if (errno == EPIPE)
  				exit(0);
-			die("git-tar-tree: %s", strerror(errno));
+			die("%s", strerror(errno));
  		} else if (!ret) {
-			die("git-tar-tree: disk full?");
+			die("disk full?");
  		}
  		size -= ret;
  		buf += ret;
@@ -308,6 +308,8 @@ int main(int argc, char **argv)
  	struct tree_desc tree;
  	struct strbuf current_path;
  
+	git_set_appname("git-tar-tree");
+
  	current_path.buf = xmalloc(PATH_MAX);
  	current_path.alloc = PATH_MAX;
  	current_path.len = current_path.eof = 0;
diff --git a/test-date.c b/test-date.c
index 93e8027..3d2cfbb 100644
--- a/test-date.c
+++ b/test-date.c
@@ -7,6 +7,8 @@ int main(int argc, char **argv)
  {
  	int i;
  
+	git_set_appname("git-test-date");
+
  	for (i = 1; i < argc; i++) {
  		char result[100];
  		time_t t;
diff --git a/test-delta.c b/test-delta.c
index 1be8ee0..bf6c6ac 100644
--- a/test-delta.c
+++ b/test-delta.c
@@ -27,6 +27,8 @@ int main(int argc, char *argv[])
  	void *from_buf, *data_buf, *out_buf;
  	unsigned long from_size, data_size, out_size;
  
+	git_set_appname("git-test-delta");
+
  	if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) {
  		fprintf(stderr, "Usage: %s\n", usage);
  		return 1;
diff --git a/tree-diff.c b/tree-diff.c
index 1cdf8aa..5170ddf 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -191,7 +191,7 @@ int diff_tree(struct tree_desc *t1, stru
  			update_tree_entry(t2);
  			continue;
  		}
-		die("git-diff-tree: internal error");
+		die("internal error");
  	}
  	return 0;
  }
diff --git a/unpack-file.c b/unpack-file.c
index 23a8562..a49e230 100644
--- a/unpack-file.c
+++ b/unpack-file.c
@@ -27,6 +27,8 @@ int main(int argc, char **argv)
  {
  	unsigned char sha1[20];
  
+	git_set_appname("git-unpack-file");
+
  	if (argc != 2 || get_sha1(argv[1], sha1))
  		usage("git-unpack-file <sha1>");
  
diff --git a/unpack-objects.c b/unpack-objects.c
index 3b824b0..315ea67 100644
--- a/unpack-objects.c
+++ b/unpack-objects.c
@@ -270,6 +270,8 @@ int main(int argc, char **argv)
  	int i;
  	unsigned char sha1[20];
  
+	git_set_appname("git-unpack-objects");
+
  	setup_git_directory();
  
  	quiet = !isatty(2);
diff --git a/update-index.c b/update-index.c
index 1efac27..1972328 100644
--- a/update-index.c
+++ b/update-index.c
@@ -370,7 +370,7 @@ static void update_one(const char *path,
  
  	if (force_remove) {
  		if (remove_file_from_cache(p))
-			die("git-update-index: unable to remove %s", path);
+			die("unable to remove %s", path);
  		report("remove '%s'", path);
  		return;
  	}
@@ -446,7 +446,7 @@ static void read_index_info(int line_ter
  		if (!mode) {
  			/* mode == 0 means there is no such path -- remove */
  			if (remove_file_from_cache(path_name))
-				die("git-update-index: unable to remove %s",
+				die("unable to remove %s",
  				    ptr);
  		}
  		else {
@@ -456,7 +456,7 @@ static void read_index_info(int line_ter
  			 */
  			ptr[-42] = ptr[-1] = 0;
  			if (add_cacheinfo(mode, sha1, path_name, stage))
-				die("git-update-index: unable to update %s",
+				die("unable to update %s",
  				    path_name);
  		}
  		if (path_name != ptr)
@@ -476,8 +476,13 @@ int main(int argc, const char **argv)
  	int i, newfd, entries, has_errors = 0, line_termination = '\n';
  	int allow_options = 1;
  	int read_from_stdin = 0;
-	const char *prefix = setup_git_directory();
-	int prefix_length = prefix ? strlen(prefix) : 0;
+	const char *prefix;
+	int prefix_length;
+
+	git_set_appname("git-unpack-index");
+
+	prefix = setup_git_directory();
+	prefix_length = prefix ? strlen(prefix) : 0;
  
  	git_config(git_default_config);
  
@@ -530,12 +535,12 @@ int main(int argc, const char **argv)
  				unsigned int mode;
  
  				if (i+3 >= argc)
-					die("git-update-index: --cacheinfo <mode> <sha1> <path>");
+					die("--cacheinfo <mode> <sha1> <path>");
  
  				if ((sscanf(argv[i+1], "%o", &mode) != 1) ||
  				    get_sha1_hex(argv[i+2], sha1) ||
  				    add_cacheinfo(mode, sha1, argv[i+3], 0))
-					die("git-update-index: --cacheinfo"
+					die("--cacheinfo"
  					    " cannot add %s", argv[i+3]);
  				i += 3;
  				continue;
@@ -543,9 +548,9 @@ int main(int argc, const char **argv)
  			if (!strcmp(path, "--chmod=-x") ||
  			    !strcmp(path, "--chmod=+x")) {
  				if (argc <= i+1)
-					die("git-update-index: %s <path>", path);
+					die("%s <path>", path);
  				if (chmod_path(path[8], argv[++i]))
-					die("git-update-index: %s cannot chmod %s", path, argv[i]);
+					die("%s cannot chmod %s", path, argv[i]);
  				continue;
  			}
  			if (!strcmp(path, "--assume-unchanged")) {
diff --git a/update-ref.c b/update-ref.c
index ba4bf51..1fd32d1 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -24,6 +24,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20], oldsha1[20], currsha1[20];
  	int fd, written;
  
+	git_set_appname("git-update-ref");
+
  	setup_git_directory();
  	git_config(git_default_config);
  	if (argc < 3 || argc > 4)
diff --git a/update-server-info.c b/update-server-info.c
index 0b6c383..3496d0e 100644
--- a/update-server-info.c
+++ b/update-server-info.c
@@ -7,6 +7,9 @@ int main(int ac, char **av)
  {
  	int i;
  	int force = 0;
+
+	git_set_appname("git-update-server-info");
+
  	for (i = 1; i < ac; i++) {
  		if (av[i][0] == '-') {
  			if (!strcmp("--force", av[i]) ||
diff --git a/upload-pack.c b/upload-pack.c
index 47560c9..4b8d690 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -38,10 +38,10 @@ static void create_pack_file(void)
  	int create_full_pack = (nr_our_refs == nr_needs && !nr_has);
  
  	if (pipe(fd) < 0)
-		die("git-upload-pack: unable to create pipe");
+		die("unable to create pipe");
  	pid = fork();
  	if (pid < 0)
-		die("git-upload-pack: unable to fork git-rev-list");
+		die("unable to fork git-rev-list");
  
  	if (!pid) {
  		int i;
@@ -84,19 +84,19 @@ static void create_pack_file(void)
  			}
  		*p++ = NULL;
  		execv_git_cmd(argv);
-		die("git-upload-pack: unable to exec git-rev-list");
+		die("unable to exec git-rev-list");
  	}
  	dup2(fd[0], 0);
  	close(fd[0]);
  	close(fd[1]);
  	execl_git_cmd("pack-objects", "--stdout", NULL);
-	die("git-upload-pack: unable to exec git-pack-objects");
+	die("unable to exec git-pack-objects");
  }
  
  static int got_sha1(char *hex, unsigned char *sha1)
  {
  	if (get_sha1_hex(hex, sha1))
-		die("git-upload-pack: expected SHA1 object, got '%s'", hex);
+		die("expected SHA1 object, got '%s'", hex);
  	if (!has_sha1_file(sha1))
  		return 0;
  	if (nr_has < MAX_HAS) {
@@ -162,7 +162,7 @@ static int get_common_commits(void)
  			packet_write(1, "NAK\n");
  			return -1;
  		}
-		die("git-upload-pack: expected SHA1 list, got '%s'", line);
+		die("expected SHA1 list, got '%s'", line);
  	}
  }
  
@@ -191,7 +191,7 @@ static int receive_needs(void)
  			sha1_buf = needs_sha1[needs];
  
  		if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf))
-			die("git-upload-pack: protocol error, "
+			die("protocol error, "
  			    "expected to get sha, not '%s'", line);
  		if (strstr(line+45, "multi_ack"))
  			multi_ack = 1;
@@ -208,7 +208,7 @@ static int receive_needs(void)
  		 */
  		o = lookup_object(sha1_buf);
  		if (!o || !(o->flags & OUR_REF))
-			die("git-upload-pack: not our ref %s", line+5);
+			die("not our ref %s", line+5);
  		if (!(o->flags & WANTED)) {
  			o->flags |= WANTED;
  			needs++;
@@ -222,7 +222,7 @@ static int send_ref(const char *refname,
  	struct object *o = parse_object(sha1);
  
  	if (!o)
-		die("git-upload-pack: cannot find object %s:", sha1_to_hex(sha1));
+		die("cannot find object %s:", sha1_to_hex(sha1));
  
  	if (capabilities)
  		packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
@@ -261,6 +261,8 @@ int main(int argc, char **argv)
  	int i;
  	int strict = 0;
  
+	git_set_appname("git-upload-pack");
+
  	for (i = 1; i < argc; i++) {
  		char *arg = argv[i];
  
diff --git a/usage.c b/usage.c
index 1fa924c..27dd5f5 100644
--- a/usage.c
+++ b/usage.c
@@ -5,8 +5,11 @@
   */
  #include "git-compat-util.h"
  
+static char appname[32+3]="";      /* +3 for ': \0' */
+
  static void report(const char *prefix, const char *err, va_list params)
  {
+	fputs(appname[0]?appname:"",stderr);
  	fputs(prefix, stderr);
  	vfprintf(stderr, err, params);
  	fputs("\n", stderr);
@@ -37,3 +40,14 @@ int error(const char *err, ...)
  	va_end(params);
  	return -1;
  }
+
+void git_set_appname(const char *name)
+{
+	size_t len=strlen(name && *name ? name : "");
+	if (0==len)
+		return;
+	memcpy(appname,name,len>sizeof(appname)-3?sizeof(appname)-3:len);
+	appname[len++]=':';
+	appname[len++]=' ';
+	appname[len++]='\0';
+}
diff --git a/var.c b/var.c
index a57a33b..a816373 100644
--- a/var.c
+++ b/var.c
@@ -54,6 +54,9 @@ static int show_config(const char *var, 
  int main(int argc, char **argv)
  {
  	const char *val;
+
+	git_set_appname("git-var");
+
  	if (argc != 2) {
  		usage(var_usage);
  	}
diff --git a/verify-pack.c b/verify-pack.c
index c99db9d..e1b3b01 100644
--- a/verify-pack.c
+++ b/verify-pack.c
@@ -35,6 +35,8 @@ int main(int ac, char **av)
  	int verbose = 0;
  	int no_more_options = 0;
  
+	git_set_appname("git-verify-pack");
+
  	while (1 < ac) {
  		char path[PATH_MAX];
  
diff --git a/write-tree.c b/write-tree.c
index dcad6e6..9f68fda 100644
--- a/write-tree.c
+++ b/write-tree.c
@@ -92,6 +92,8 @@ int main(int argc, char **argv)
  	int entries;
  	unsigned char sha1[20];
  	
+	git_set_appname("git-write-tree");
+
  	setup_git_directory();
  
  	entries = read_cache();
@@ -106,7 +108,7 @@ int main(int argc, char **argv)
  		die("too many options");
  
  	if (entries < 0)
-		die("git-write-tree: error reading cache");
+		die("error reading cache");
  
  	/* Verify that the tree is merged */
  	funny = 0;
@@ -121,7 +123,7 @@ int main(int argc, char **argv)
  		}
  	}
  	if (funny)
-		die("git-write-tree: not able to write tree");
+		die("not able to write tree");
  
  	/* Also verify that the cache does not have path and path/file
  	 * at the same time.  At this point we know the cache has only
@@ -148,11 +150,11 @@ int main(int argc, char **argv)
  		}
  	}
  	if (funny)
-		die("git-write-tree: not able to write tree");
+		die("not able to write tree");
  
  	/* Ok, write it out */
  	if (write_tree(active_cache, entries, "", 0, sha1) != entries)
-		die("git-write-tree: internal error");
+		die("internal error");
  	printf("%s\n", sha1_to_hex(sha1));
  	return 0;
  }
-- 
1.3.0.ge649-dirty

^ permalink raw reply related

* Re: [PATCH] Make die() and error() prefix line with binary name if set
From: Jakub Narebski @ 2006-04-25 10:22 UTC (permalink / raw)
  To: git
In-Reply-To: <20060425101207.GC5482@bolero.cs.tu-berlin.de>

Rocco Rutte wrote:

> +        size_t len=strlen(name && *name ? name : "");
> +        if (0==len)

Wouldn't it be easier (and less idiomatic) to just do

+        size_t len= *name ? strlen(name) : 0;
+        if (0==len)

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* [PATCH] Make die() and error() prefix line with binary name if set
From: Rocco Rutte @ 2006-04-25 14:08 UTC (permalink / raw)
  To: git

Since lots of logic is implemented via shell scripts, it's in
general useful to print out where an error occured. Previously
only some commands manually added the binary name to die() and
error() calls.

Now, git_set_appname() can be used to set the name of the binary
as first call in a binary's main() routine which will be used
as prefix in die() and error(). If it was not called, no prefix
will be printed.

Also fix minor identation issues.

Signed-off-by: Rocco Rutte <pdmef@gmx.net>

---

  apply.c              |   13 +++++++------
  blame.c              |    2 ++
  cat-file.c           |   10 ++++++----
  check-ref-format.c   |    2 ++
  checkout-index.c     |    8 +++++---
  clone-pack.c         |    2 ++
  commit-tree.c        |    2 ++
  connect.c            |    4 ++--
  convert-objects.c    |    2 ++
  daemon.c             |    4 +++-
  describe.c           |    2 ++
  diff-files.c         |    5 ++++-
  diff-index.c         |    5 ++++-
  diff-stages.c        |    5 ++++-
  diff-tree.c          |    2 ++
  entry.c              |   14 +++++++-------
  fetch-clone.c        |    8 +++-----
  fetch-pack.c         |    4 +++-
  fsck-objects.c       |    2 ++
  get-tar-commit-id.c  |    2 ++
  git-compat-util.h    |    1 +
  git.c                |    2 ++
  hash-object.c        |    2 ++
  http-fetch.c         |    2 ++
  http-push.c          |    5 +++--
  index-pack.c         |   17 +++++++----------
  init-db.c            |    2 ++
  local-fetch.c        |    2 ++
  ls-files.c           |    8 +++++---
  ls-tree.c            |    2 ++
  mailinfo.c           |    2 ++
  mailsplit.c          |    2 ++
  merge-base.c         |    2 ++
  merge-index.c        |    8 +++++---
  merge-tree.c         |    2 ++
  mktag.c              |    2 ++
  mktree.c             |    2 ++
  name-rev.c           |    2 ++
  pack-objects.c       |    5 +++--
  pack-redundant.c     |    2 ++
  patch-id.c           |    2 ++
  peek-remote.c        |    2 ++
  prune-packed.c       |    2 ++
  read-tree.c          |    5 +++--
  receive-pack.c       |    5 +++--
  repo-config.c        |    2 ++
  rev-list.c           |    2 ++
  rev-parse.c          |    5 ++++-
  send-pack.c          |    2 ++
  shell.c              |    2 ++
  show-branch.c        |    2 ++
  show-index.c         |    2 ++
  ssh-fetch.c          |    2 ++
  ssh-upload.c         |    2 ++
  stripspace.c         |    2 ++
  symbolic-ref.c       |    2 ++
  tar-tree.c           |    6 ++++--
  test-date.c          |    2 ++
  test-delta.c         |    2 ++
  tree-diff.c          |    2 +-
  unpack-file.c        |    2 ++
  unpack-objects.c     |    2 ++
  update-index.c       |   26 ++++++++++++++------------
  update-ref.c         |    2 ++
  update-server-info.c |    3 +++
  upload-pack.c        |   21 +++++++++++----------
  usage.c              |   14 ++++++++++++++
  var.c                |    3 +++
  verify-pack.c        |    2 ++
  write-tree.c         |   10 ++++++----
  70 files changed, 222 insertions(+), 86 deletions(-)

cb3d0f89bcead397d38e3445c1925d1107bcf062
diff --git a/apply.c b/apply.c
index 269210a..90c4c7c 100644
--- a/apply.c
+++ b/apply.c
@@ -142,7 +142,7 @@ static void *read_patch_file(int fd, uns
  		if (!nr)
  			break;
  		if (nr < 0)
-			die("git-apply: read returned %s", strerror(errno));
+			die("read returned %s", strerror(errno));
  		size += nr;
  	}
  	*sizep = size;
@@ -320,17 +320,17 @@ static char *gitdiff_verify_name(const c
  		name = orig_name;
  		len = strlen(name);
  		if (isnull)
-			die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
+			die("bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
  		another = find_name(line, NULL, 1, 0);
  		if (!another || memcmp(another, name, len))
-			die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
+			die("bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
  		free(another);
  		return orig_name;
  	}
  	else {
  		/* expect "/dev/null" */
  		if (memcmp("/dev/null", line, 9) || line[9] != '\n')
-			die("git-apply: bad git-diff - expected /dev/null on line %d", linenr);
+			die("bad git-diff - expected /dev/null on line %d", linenr);
  		return NULL;
  	}
  }
@@ -1570,8 +1570,7 @@ static void show_index_list(struct patch
  		if (patch->is_new)
  			sha1_ptr = null_sha1;
  		else if (get_sha1(patch->old_sha1_prefix, sha1))
-			die("sha1 information is lacking or useless (%s).",
-			    name);
+			die("sha1 information is lacking or useless (%s).", name);
  		else
  			sha1_ptr = sha1;
  
@@ -1960,6 +1959,8 @@ int main(int argc, char **argv)
  	int read_stdin = 1;
  	const char *whitespace_option = NULL;
  
+	git_set_appname("git-apply");
+
  	for (i = 1; i < argc; i++) {
  		const char *arg = argv[i];
  		char *end;
diff --git a/blame.c b/blame.c
index 07d2d27..804f108 100644
--- a/blame.c
+++ b/blame.c
@@ -752,6 +752,8 @@ int main(int argc, const char **argv)
  	int longest_file, longest_author;
  	int found_rename;
  
+	git_set_appname("git-blame");
+
  	const char* prefix = setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/cat-file.c b/cat-file.c
index 628f6ca..75c400a 100644
--- a/cat-file.c
+++ b/cat-file.c
@@ -16,9 +16,9 @@ static void flush_buffer(const char *buf
  			/* Ignore epipe */
  			if (errno == EPIPE)
  				break;
-			die("git-cat-file: %s", strerror(errno));
+			die("%s", strerror(errno));
  		} else if (!ret) {
-			die("git-cat-file: disk full?");
+			die("disk full?");
  		}
  		size -= ret;
  		buf += ret;
@@ -101,6 +101,8 @@ int main(int argc, char **argv)
  	unsigned long size;
  	int opt;
  
+	git_set_appname("git-cat-file");
+
  	setup_git_directory();
  	git_config(git_default_config);
  	if (argc != 3 || get_sha1(argv[2], sha1))
@@ -154,11 +156,11 @@ int main(int argc, char **argv)
  		break;
  
  	default:
-		die("git-cat-file: unknown option: %s\n", argv[1]);
+		die("unknown option: %s\n", argv[1]);
  	}
  
  	if (!buf)
-		die("git-cat-file %s: bad file", argv[2]);
+		die("bad file", argv[2]);
  
  	flush_buffer(buf, size);
  	return 0;
diff --git a/check-ref-format.c b/check-ref-format.c
index a0adb3d..ce08eda 100644
--- a/check-ref-format.c
+++ b/check-ref-format.c
@@ -9,6 +9,8 @@ #include <stdio.h>
  
  int main(int ac, char **av)
  {
+	git_set_appname("git-check-ref-format");
+
  	if (ac != 2)
  		usage("git-check-ref-format refname");
  	if (check_ref_format(av[1]))
diff --git a/checkout-index.c b/checkout-index.c
index dd6a2d8..b515651 100644
--- a/checkout-index.c
+++ b/checkout-index.c
@@ -176,6 +176,8 @@ int main(int argc, char **argv)
  	int all = 0;
  	int read_from_stdin = 0;
  
+	git_set_appname("git-checkout-index");
+
  	prefix = setup_git_directory();
  	git_config(git_default_config);
  	prefix_length = prefix ? strlen(prefix) : 0;
@@ -271,16 +273,16 @@ int main(int argc, char **argv)
  		const char *arg = argv[i];
  
  		if (all)
-			die("git-checkout-index: don't mix '--all' and explicit filenames");
+			die("don't mix '--all' and explicit filenames");
  		if (read_from_stdin)
-			die("git-checkout-index: don't mix '--stdin' and explicit filenames");
+			die("don't mix '--stdin' and explicit filenames");
  		checkout_file(prefix_path(prefix, prefix_length, arg));
  	}
  
  	if (read_from_stdin) {
  		struct strbuf buf;
  		if (all)
-			die("git-checkout-index: don't mix '--all' and '--stdin'");
+			die("don't mix '--all' and '--stdin'");
  		strbuf_init(&buf);
  		while (1) {
  			char *path_name;
diff --git a/clone-pack.c b/clone-pack.c
index a4370f5..0139745 100644
--- a/clone-pack.c
+++ b/clone-pack.c
@@ -150,6 +150,8 @@ int main(int argc, char **argv)
  	int fd[2];
  	pid_t pid;
  
+	git_set_appname("git-clone-pack");
+
  	setup_git_directory();
  
  	nr_heads = 0;
diff --git a/commit-tree.c b/commit-tree.c
index 2d86518..e07b0eb 100644
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -87,6 +87,8 @@ int main(int argc, char **argv)
  	char *buffer;
  	unsigned int size;
  
+	git_set_appname("git-commit-tree");
+
  	setup_ident();
  	setup_git_directory();
  
diff --git a/connect.c b/connect.c
index 6a8f8a6..70ab5ad 100644
--- a/connect.c
+++ b/connect.c
@@ -69,7 +69,7 @@ int get_ack(int fd, unsigned char *resul
  	int len = packet_read_line(fd, line, sizeof(line));
  
  	if (!len)
-		die("git-fetch-pack: expected ACK/NAK, got EOF");
+		die("expected ACK/NAK, got EOF");
  	if (line[len-1] == '\n')
  		line[--len] = 0;
  	if (!strcmp(line, "NAK"))
@@ -81,7 +81,7 @@ int get_ack(int fd, unsigned char *resul
  			return 1;
  		}
  	}
-	die("git-fetch_pack: expected ACK/NAK, got '%s'", line);
+	die("expected ACK/NAK, got '%s'", line);
  }
  
  int path_match(const char *path, int nr, char **match)
diff --git a/convert-objects.c b/convert-objects.c
index 12aacef..6b5d955 100644
--- a/convert-objects.c
+++ b/convert-objects.c
@@ -319,6 +319,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20];
  	struct entry *entry;
  
+	git_set_appname("git-convert-object");
+
  	setup_git_directory();
  
  	if (argc != 2 || get_sha1(argv[1], sha1))
diff --git a/daemon.c b/daemon.c
index 776749e..0bb84e8 100644
--- a/daemon.c
+++ b/daemon.c
@@ -666,6 +666,8 @@ int main(int argc, char **argv)
  	int inetd_mode = 0;
  	int i;
  
+	git_set_appname("git-daemon");
+
  	for (i = 1; i < argc; i++) {
  		char *arg = argv[i];
  
@@ -739,7 +741,7 @@ int main(int argc, char **argv)
  
  	if (strict_paths && (!ok_paths || !*ok_paths)) {
  		if (!inetd_mode)
-			die("git-daemon: option --strict-paths requires a whitelist");
+			die("option --strict-paths requires a whitelist");
  
  		logerror("option --strict-paths requires a whitelist");
  		exit (1);
diff --git a/describe.c b/describe.c
index ff65742..a882d00 100644
--- a/describe.c
+++ b/describe.c
@@ -143,6 +143,8 @@ int main(int argc, char **argv)
  {
  	int i;
  
+	git_set_appname("git-describe");
+
  	for (i = 1; i < argc; i++) {
  		const char *arg = argv[i];
  
diff --git a/diff-files.c b/diff-files.c
index ffbef48..0c99c00 100644
--- a/diff-files.c
+++ b/diff-files.c
@@ -39,9 +39,12 @@ static void show_modified(int oldmode, i
  int main(int argc, const char **argv)
  {
  	const char **pathspec;
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	int entries, i;
  
+	git_set_appname("git-diff-files");
+
+	prefix = setup_git_directory();
  	git_config(git_diff_config);
  	diff_setup(&rev.diffopt);
  	while (1 < argc && argv[1][0] == '-') {
diff --git a/diff-index.c b/diff-index.c
index e376d65..b066d48 100644
--- a/diff-index.c
+++ b/diff-index.c
@@ -171,13 +171,16 @@ int main(int argc, const char **argv)
  {
  	const char *tree_name = NULL;
  	unsigned char sha1[20];
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	const char **pathspec = NULL;
  	struct tree *tree;
  	int ret;
  	int allow_options = 1;
  	int i;
  
+	git_set_appname("git-diff-index");
+
+	prefix = setup_git_directory();
  	git_config(git_diff_config);
  	diff_setup(&diff_options);
  	for (i = 1; i < argc; i++) {
diff --git a/diff-stages.c b/diff-stages.c
index dcd20e7..bd40b8e 100644
--- a/diff-stages.c
+++ b/diff-stages.c
@@ -57,9 +57,12 @@ static void diff_stages(int stage1, int 
  int main(int ac, const char **av)
  {
  	int stage1, stage2;
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	const char **pathspec = NULL;
  
+	git_set_appname("git-diff-stages");
+
+	prefix = setup_git_directory();
  	git_config(git_diff_config);
  	read_cache();
  	diff_setup(&diff_options);
diff --git a/diff-tree.c b/diff-tree.c
index 7207867..76222d5 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -67,6 +67,8 @@ int main(int argc, const char **argv)
  	struct object_list *list;
  	int read_stdin = 0;
  
+	git_set_appname("git-diff-tree");
+
  	git_config(git_diff_config);
  	nr_sha1 = 0;
  	init_revisions(opt);
diff --git a/entry.c b/entry.c
index 793724f..5cf36f9 100644
--- a/entry.c
+++ b/entry.c
@@ -76,7 +76,7 @@ static int write_entry(struct cache_entr
  	if (!new || strcmp(type, blob_type)) {
  		if (new)
  			free(new);
-		return error("git-checkout-index: unable to read sha1 file of %s (%s)",
+		return error("unable to read sha1 file of %s (%s)",
  			path, sha1_to_hex(ce->sha1));
  	}
  	switch (ntohl(ce->ce_mode) & S_IFMT) {
@@ -88,14 +88,14 @@ static int write_entry(struct cache_entr
  			fd = create_file(path, ntohl(ce->ce_mode));
  		if (fd < 0) {
  			free(new);
-			return error("git-checkout-index: unable to create file %s (%s)",
+			return error("unable to create file %s (%s)",
  				path, strerror(errno));
  		}
  		wrote = write(fd, new, size);
  		close(fd);
  		free(new);
  		if (wrote != size)
-			return error("git-checkout-index: unable to write file %s", path);
+			return error("unable to write file %s", path);
  		break;
  	case S_IFLNK:
  		if (to_tempfile) {
@@ -103,26 +103,26 @@ static int write_entry(struct cache_entr
  			fd = mkstemp(path);
  			if (fd < 0) {
  				free(new);
-				return error("git-checkout-index: unable to create "
+				return error("unable to create "
  						 "file %s (%s)", path, strerror(errno));
  			}
  			wrote = write(fd, new, size);
  			close(fd);
  			free(new);
  			if (wrote != size)
-				return error("git-checkout-index: unable to write file %s",
+				return error("unable to write file %s",
  					path);
  		} else {
  			wrote = symlink(new, path);
  			free(new);
  			if (wrote)
-				return error("git-checkout-index: unable to create "
+				return error("unable to create "
  						 "symlink %s (%s)", path, strerror(errno));
  		}
  		break;
  	default:
  		free(new);
-		return error("git-checkout-index: unknown file mode for %s", path);
+		return error("unknown file mode for %s", path);
  	}
  
  	if (state->refresh_cache) {
diff --git a/fetch-clone.c b/fetch-clone.c
index da1b3ff..d94c252 100644
--- a/fetch-clone.c
+++ b/fetch-clone.c
@@ -23,7 +23,7 @@ static int finish_pack(const char *pack_
  
  	pid = fork();
  	if (pid < 0)
-		die("git-clone-pack: unable to fork off git-index-pack");
+		die("unable to fork off git-index-pack");
  	if (!pid) {
  		close(0);
  		dup2(pipe_fd[1], 1);
@@ -113,14 +113,12 @@ int receive_unpack_pack(int fd[2], const
  	close(fd[1]);
  	while (waitpid(pid, &status, 0) < 0) {
  		if (errno != EINTR)
-			die("waiting for git-unpack-objects: %s",
-			    strerror(errno));
+			die("waiting for git-unpack-objects: %s", strerror(errno));
  	}
  	if (WIFEXITED(status)) {
  		int code = WEXITSTATUS(status);
  		if (code)
-			die("git-unpack-objects died with error code %d",
-			    code);
+			die("git-unpack-objects died with error code %d", code);
  		return 0;
  	}
  	if (WIFSIGNALED(status)) {
diff --git a/fetch-pack.c b/fetch-pack.c
index a3bcad0..f7053e7 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -390,7 +390,7 @@ static int fetch_pack(int fd[2], int nr_
  		status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
  
  	if (status)
-		die("git-fetch-pack: fetch failed.");
+		die("fetch failed.");
  
   all_done:
  	while (ref) {
@@ -408,6 +408,8 @@ int main(int argc, char **argv)
  	int fd[2];
  	pid_t pid;
  
+	git_set_appname("git-fetch-pack");
+
  	setup_git_directory();
  
  	nr_heads = 0;
diff --git a/fsck-objects.c b/fsck-objects.c
index 59b2590..5e004b6 100644
--- a/fsck-objects.c
+++ b/fsck-objects.c
@@ -442,6 +442,8 @@ int main(int argc, char **argv)
  {
  	int i, heads;
  
+	git_set_appname("git-fsck-objects");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/get-tar-commit-id.c b/get-tar-commit-id.c
index 4166290..036094d 100644
--- a/get-tar-commit-id.c
+++ b/get-tar-commit-id.c
@@ -12,6 +12,8 @@ int main(int argc, char **argv)
  	char buffer[HEADERSIZE];
  	ssize_t n;
  
+	git_set_appname("git-get-tar-commit-id");
+
  	n = read(0, buffer, HEADERSIZE);
  	if (n < HEADERSIZE) {
  		fprintf(stderr, "read error\n");
diff --git a/git-compat-util.h b/git-compat-util.h
index 5d543d2..cc5370c 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -39,6 +39,7 @@ #endif
  extern void usage(const char *err) NORETURN;
  extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
  extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void git_set_appname(const char *name);
  
  #ifdef NO_MMAP
  
diff --git a/git.c b/git.c
index aa2b814..ad49bb7 100644
--- a/git.c
+++ b/git.c
@@ -71,6 +71,8 @@ int main(int argc, const char **argv, ch
  	char git_command[PATH_MAX + 1];
  	const char *exec_path = NULL;
  
+	git_set_appname("git");
+
  	/*
  	 * Take the basename of argv[0] as the command
  	 * name, and the dirname as the default exec_path
diff --git a/hash-object.c b/hash-object.c
index 43bd93b..0c95d05 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -42,6 +42,8 @@ int main(int argc, char **argv)
  	int prefix_length = -1;
  	int no_more_flags = 0;
  
+	git_set_appname("git-hash-object");
+
  	for (i = 1 ; i < argc; i++) {
  		if (!no_more_flags && argv[i][0] == '-') {
  			if (!strcmp(argv[i], "-t")) {
diff --git a/http-fetch.c b/http-fetch.c
index 861644b..69c7cdb 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -1222,6 +1222,8 @@ int main(int argc, char **argv)
  	int arg = 1;
  	int rc = 0;
  
+	git_set_appname("git-http-fetch");
+
  	setup_git_directory();
  
  	while (arg < argc && argv[arg][0] == '-') {
diff --git a/http-push.c b/http-push.c
index b4327d9..0ff5b05 100644
--- a/http-push.c
+++ b/http-push.c
@@ -2130,8 +2130,7 @@ static void fetch_symref(char *path, cha
  	if (start_active_slot(slot)) {
  		run_active_slot(slot);
  		if (results.curl_result != CURLE_OK) {
-			die("Couldn't get %s for remote symref\n%s",
-			    url, curl_errorstr);
+			die("Couldn't get %s for remote symref\n%s", url, curl_errorstr);
  		}
  	} else {
  		die("Unable to start remote symref request");
@@ -2315,6 +2314,8 @@ int main(int argc, char **argv)
  	int new_refs;
  	struct ref *ref;
  
+	git_set_appname("git-http-push");
+
  	setup_git_directory();
  	setup_ident();
  
diff --git a/index-pack.c b/index-pack.c
index b39953d..bcfd116 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -39,21 +39,18 @@ static void open_pack_file(void)
  
  	fd = open(pack_name, O_RDONLY);
  	if (fd < 0)
-		die("cannot open packfile '%s': %s", pack_name,
-		    strerror(errno));
+		die("cannot open packfile '%s': %s", pack_name, strerror(errno));
  	if (fstat(fd, &st)) {
  		int err = errno;
  		close(fd);
-		die("cannot fstat packfile '%s': %s", pack_name,
-		    strerror(err));
+		die("cannot fstat packfile '%s': %s", pack_name, strerror(err));
  	}
  	pack_size = st.st_size;
  	pack_base = mmap(NULL, pack_size, PROT_READ, MAP_PRIVATE, fd, 0);
  	if (pack_base == MAP_FAILED) {
  		int err = errno;
  		close(fd);
-		die("cannot mmap packfile '%s': %s", pack_name,
-		    strerror(err));
+		die("cannot mmap packfile '%s': %s", pack_name, strerror(err));
  	}
  	close(fd);
  }
@@ -97,8 +94,7 @@ static void bad_object(unsigned long off
  	va_start(params, format);
  	vsnprintf(buf, sizeof(buf), format, params);
  	va_end(params);
-	die("packfile '%s': bad object at offset %lu: %s",
-	    pack_name, offset, buf);
+	die("packfile '%s': bad object at offset %lu: %s", pack_name, offset, buf);
  }
  
  static void *unpack_entry_data(unsigned long offset,
@@ -425,6 +421,8 @@ int main(int argc, char **argv)
  	char *index_name_buf = NULL;
  	unsigned char sha1[20];
  
+	git_set_appname("git-index-pack");
+
  	for (i = 1; i < argc; i++) {
  		const char *arg = argv[i];
  
@@ -448,8 +446,7 @@ int main(int argc, char **argv)
  	if (!index_name) {
  		int len = strlen(pack_name);
  		if (len < 5 || strcmp(pack_name + len - 5, ".pack"))
-			die("packfile name '%s' does not end with '.pack'",
-			    pack_name);
+			die("packfile name '%s' does not end with '.pack'", pack_name);
  		index_name_buf = xmalloc(len);
  		memcpy(index_name_buf, pack_name, len - 5);
  		strcpy(index_name_buf + len - 5, ".idx");
diff --git a/init-db.c b/init-db.c
index ff29496..29c93e3 100644
--- a/init-db.c
+++ b/init-db.c
@@ -241,6 +241,8 @@ int main(int argc, char **argv)
  	char *path, *template_dir = NULL;
  	int len, i;
  
+	git_set_appname("git-init-db");
+
  	for (i = 1; i < argc; i++, argv++) {
  		char *arg = argv[1];
  		if (!strncmp(arg, "--template=", 11))
diff --git a/local-fetch.c b/local-fetch.c
index fa9e697..11bf6f8 100644
--- a/local-fetch.c
+++ b/local-fetch.c
@@ -207,6 +207,8 @@ int main(int argc, char **argv)
  	char *commit_id;
  	int arg = 1;
  
+	git_set_appname("git-local-fetch");
+
  	setup_git_directory();
  
  	while (arg < argc && argv[arg][0] == '-') {
diff --git a/ls-files.c b/ls-files.c
index 4a4af1c..15a9bb2 100644
--- a/ls-files.c
+++ b/ls-files.c
@@ -383,7 +383,7 @@ static void show_dir_entry(const char *t
  	int offset = prefix_offset;
  
  	if (len >= ent->len)
-		die("git-ls-files: internal error - directory entry not superset of prefix");
+		die("internal error - directory entry not superset of prefix");
  
  	if (pathspec && !match(pathspec, ps_matched, ent->name, len))
  		return;
@@ -471,7 +471,7 @@ static void show_ce_entry(const char *ta
  	int offset = prefix_offset;
  
  	if (len >= ce_namelen(ce))
-		die("git-ls-files: internal error - cache entry not superset of prefix");
+		die("internal error - cache entry not superset of prefix");
  
  	if (pathspec && !match(pathspec, ps_matched, ce->name, len))
  		return;
@@ -630,7 +630,7 @@ static void verify_pathspec(void)
  	}
  
  	if (prefix_offset > max || memcmp(prev, prefix, prefix_offset))
-		die("git-ls-files: cannot generate relative filenames containing '..'");
+		die("cannot generate relative filenames containing '..'");
  
  	real_prefix = NULL;
  	prefix_len = max;
@@ -653,6 +653,8 @@ int main(int argc, const char **argv)
  	int i;
  	int exc_given = 0;
  
+	git_set_appname("git-ls-files");
+
  	prefix = setup_git_directory();
  	if (prefix)
  		prefix_offset = strlen(prefix);
diff --git a/ls-tree.c b/ls-tree.c
index e4ef200..e037bf0 100644
--- a/ls-tree.c
+++ b/ls-tree.c
@@ -89,6 +89,8 @@ int main(int argc, const char **argv)
  	unsigned char sha1[20];
  	struct tree *tree;
  
+	git_set_appname("git-ls-tree");
+
  	prefix = setup_git_directory();
  	git_config(git_default_config);
  	if (prefix && *prefix)
diff --git a/mailinfo.c b/mailinfo.c
index b276519..7baa3ff 100644
--- a/mailinfo.c
+++ b/mailinfo.c
@@ -757,6 +757,8 @@ static const char mailinfo_usage[] =
  
  int main(int argc, char **argv)
  {
+	git_set_appname("git-mailinfo");
+
  	/* NEEDSWORK: might want to do the optional .git/ directory
  	 * discovery
  	 */
diff --git a/mailsplit.c b/mailsplit.c
index c529e2d..686920e 100644
--- a/mailsplit.c
+++ b/mailsplit.c
@@ -111,6 +111,8 @@ int main(int argc, const char **argv)
  	static const char *stdin_only[] = { "-", NULL };
  	char *name;
  
+	git_set_appname("git-mailsplit");
+
  	for (argp = argv+1; *argp; argp++) {
  		const char *arg = *argp;
  
diff --git a/merge-base.c b/merge-base.c
index 07f5ab4..29cdbd7 100644
--- a/merge-base.c
+++ b/merge-base.c
@@ -236,6 +236,8 @@ int main(int argc, char **argv)
  	struct commit *rev1, *rev2;
  	unsigned char rev1key[20], rev2key[20];
  
+	git_set_appname("git-merge-base");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/merge-index.c b/merge-index.c
index 024196e..3430da5 100644
--- a/merge-index.c
+++ b/merge-index.c
@@ -42,7 +42,7 @@ static int merge_entry(int pos, const ch
  	int found;
  	
  	if (pos >= active_nr)
-		die("git-merge-index: %s not in the cache", path);
+		die("%s not in the cache", path);
  	arguments[0] = pgm;
  	arguments[1] = "";
  	arguments[2] = "";
@@ -67,7 +67,7 @@ static int merge_entry(int pos, const ch
  		arguments[stage + 4] = ownbuf[stage];
  	} while (++pos < active_nr);
  	if (!found)
-		die("git-merge-index: %s not in the cache", path);
+		die("%s not in the cache", path);
  	run_program();
  	return found;
  }
@@ -99,6 +99,8 @@ int main(int argc, char **argv)
  {
  	int i, force_file = 0;
  
+	git_set_appname("git-merge-index");
+
  	if (argc < 3)
  		usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
  
@@ -126,7 +128,7 @@ int main(int argc, char **argv)
  				merge_all();
  				continue;
  			}
-			die("git-merge-index: unknown option %s", arg);
+			die("unknown option %s", arg);
  		}
  		merge_file(arg);
  	}
diff --git a/merge-tree.c b/merge-tree.c
index 50528d5..1eca1d7 100644
--- a/merge-tree.c
+++ b/merge-tree.c
@@ -164,6 +164,8 @@ int main(int argc, char **argv)
  	struct tree_desc t[3];
  	void *buf1, *buf2, *buf3;
  
+	git_set_appname("git-merge-tree");
+
  	if (argc < 4)
  		usage(merge_tree_usage);
  
diff --git a/mktag.c b/mktag.c
index 2328878..dcc917e 100644
--- a/mktag.c
+++ b/mktag.c
@@ -109,6 +109,8 @@ int main(int argc, char **argv)
  	char buffer[MAXSIZE];
  	unsigned char result_sha1[20];
  
+	git_set_appname("git-mktag");
+
  	if (argc != 1)
  		usage("cat <signaturefile> | git-mktag");
  
diff --git a/mktree.c b/mktree.c
index ab63cd9..a1ac929 100644
--- a/mktree.c
+++ b/mktree.c
@@ -79,6 +79,8 @@ int main(int ac, char **av)
  	unsigned char sha1[20];
  	int line_termination = '\n';
  
+	git_set_appname("git-mktree");
+
  	setup_git_directory();
  
  	while ((1 < ac) && av[1][0] == '-') {
diff --git a/name-rev.c b/name-rev.c
index bad8a53..c426059 100644
--- a/name-rev.c
+++ b/name-rev.c
@@ -126,6 +126,8 @@ int main(int argc, char **argv)
  	struct object_list **walker = &revs;
  	int as_is = 0, all = 0, transform_stdin = 0;
  
+	git_set_appname("git-name-rev");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/pack-objects.c b/pack-objects.c
index c0acc46..ecbe9f9 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -1237,6 +1237,8 @@ int main(int argc, char **argv)
  	int num_preferred_base = 0;
  	int i;
  
+	git_set_appname("git-pack-objects");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
@@ -1315,8 +1317,7 @@ int main(int argc, char **argv)
  
  		if (line[0] == '-') {
  			if (get_sha1_hex(line+1, sha1))
-				die("expected edge sha1, got garbage:\n %s",
-				    line+1);
+				die("expected edge sha1, got garbage:\n %s", line+1);
  			if (num_preferred_base++ < window)
  				add_preferred_base(sha1);
  			continue;
diff --git a/pack-redundant.c b/pack-redundant.c
index cd81f5a..e2eff1b 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -589,6 +589,8 @@ int main(int argc, char **argv)
  	unsigned char *sha1;
  	char buf[42]; /* 40 byte sha1 + \n + \0 */
  
+	git_set_appname("git-pack-redundant");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/patch-id.c b/patch-id.c
index edbc4aa..0e2bd85 100644
--- a/patch-id.c
+++ b/patch-id.c
@@ -74,6 +74,8 @@ static const char patch_id_usage[] = "gi
  
  int main(int argc, char **argv)
  {
+	git_set_appname("git-patch-id");
+
  	if (argc != 1)
  		usage(patch_id_usage);
  
diff --git a/peek-remote.c b/peek-remote.c
index a90cf22..99dac1b 100644
--- a/peek-remote.c
+++ b/peek-remote.c
@@ -29,6 +29,8 @@ int main(int argc, char **argv)
  	pid_t pid;
  	int nongit = 0;
  
+	git_set_appname("git-pack-remote");
+
  	setup_git_directory_gently(&nongit);
  
  	for (i = 1; i < argc; i++) {
diff --git a/prune-packed.c b/prune-packed.c
index d24b097..106cc39 100644
--- a/prune-packed.c
+++ b/prune-packed.c
@@ -58,6 +58,8 @@ int main(int argc, char **argv)
  {
  	int i;
  
+	git_set_appname("git-prune-packed");
+
  	setup_git_directory();
  
  	for (i = 1; i < argc; i++) {
diff --git a/read-tree.c b/read-tree.c
index 26f4f7e..6e1b698 100644
--- a/read-tree.c
+++ b/read-tree.c
@@ -235,8 +235,7 @@ #endif
  
  static void reject_merge(struct cache_entry *ce)
  {
-	die("Entry '%s' would be overwritten by merge. Cannot merge.", 
-	    ce->name);
+	die("Entry '%s' would be overwritten by merge. Cannot merge.", ce->name);
  }
  
  /* Unlink the last component and attempt to remove leading
@@ -723,6 +722,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20];
  	merge_fn_t fn = NULL;
  
+	git_set_appname("git-read-tree");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/receive-pack.c b/receive-pack.c
index 93929b5..54ec6dc 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -237,8 +237,7 @@ static void read_head_info(void)
  		    line[81] != ' ' ||
  		    get_sha1_hex(line, old_sha1) ||
  		    get_sha1_hex(line + 41, new_sha1))
-			die("protocol error: expected old/new/ref, got '%s'",
-			    line);
+			die("protocol error: expected old/new/ref, got '%s'", line);
  
  		refname = line + 82;
  		reflen = strlen(refname);
@@ -304,6 +303,8 @@ int main(int argc, char **argv)
  	int i;
  	char *dir = NULL;
  
+	git_set_appname("git-receive-pack");
+
  	argv++;
  	for (i = 1; i < argc; i++) {
  		char *arg = *argv++;
diff --git a/repo-config.c b/repo-config.c
index c5ebb76..793af68 100644
--- a/repo-config.c
+++ b/repo-config.c
@@ -86,6 +86,8 @@ static int get_value(const char* key_, c
  
  int main(int argc, const char **argv)
  {
+	git_set_appname("git-repo-config");
+
  	setup_git_directory();
  
  	while (1 < argc) {
diff --git a/rev-list.c b/rev-list.c
index 8b0ec38..4646372 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -296,6 +296,8 @@ int main(int argc, const char **argv)
  	struct commit_list *list;
  	int i;
  
+	git_set_appname("git-rev-list");
+
  	init_revisions(&revs);
  	revs.abbrev = 0;
  	revs.commit_format = CMIT_FMT_UNSPECIFIED;
diff --git a/rev-parse.c b/rev-parse.c
index 7f66ae2..aaaf813 100644
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -172,8 +172,11 @@ int main(int argc, char **argv)
  {
  	int i, as_is = 0, verify = 0;
  	unsigned char sha1[20];
-	const char *prefix = setup_git_directory();
+	const char *prefix;
  	
+	git_set_appname("git-rev-parse");
+
+	prefix = setup_git_directory();
  	git_config(git_default_config);
  
  	for (i = 1; i < argc; i++) {
diff --git a/send-pack.c b/send-pack.c
index 409f188..803e193 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -361,6 +361,8 @@ int main(int argc, char **argv)
  	int fd[2], ret;
  	pid_t pid;
  
+	git_set_appname("git-send-pack");
+
  	setup_git_directory();
  	git_config(git_default_config);
  
diff --git a/shell.c b/shell.c
index 8c08cf0..c22cde1 100644
--- a/shell.c
+++ b/shell.c
@@ -32,6 +32,8 @@ int main(int argc, char **argv)
  	char *prog;
  	struct commands *cmd;
  
+	git_set_appname("git-shell");
+
  	/* We want to see "-c cmd args", and nothing else */
  	if (argc != 3 || strcmp(argv[1], "-c"))
  		die("What do you think I am? A shell?");
diff --git a/show-branch.c b/show-branch.c
index 24efb65..9ec3553 100644
--- a/show-branch.c
+++ b/show-branch.c
@@ -549,6 +549,8 @@ int main(int ac, char **av)
  	int head_at = -1;
  	int topics = 0;
  
+	git_set_appname("git-show-branch");
+
  	setup_git_directory();
  	git_config(git_show_branch_config);
  
diff --git a/show-index.c b/show-index.c
index c21d660..b8a9fba 100644
--- a/show-index.c
+++ b/show-index.c
@@ -7,6 +7,8 @@ int main(int argc, char **argv)
  	unsigned int entry[6];
  	static unsigned int top_index[256];
  
+	git_set_appname("git-show-index");
+
  	if (fread(top_index, sizeof(top_index), 1, stdin) != 1)
  		die("unable to read idex");
  	nr = 0;
diff --git a/ssh-fetch.c b/ssh-fetch.c
index 4eb9e04..4bab7e7 100644
--- a/ssh-fetch.c
+++ b/ssh-fetch.c
@@ -128,6 +128,8 @@ int main(int argc, char **argv)
  	int arg = 1;
  	const char *prog;
  
+	git_set_appname("git-ssh-fetch");
+
  	prog = getenv("GIT_SSH_PUSH");
  	if (!prog) prog = "git-ssh-upload";
  
diff --git a/ssh-upload.c b/ssh-upload.c
index b675a0b..9860cf4 100644
--- a/ssh-upload.c
+++ b/ssh-upload.c
@@ -119,6 +119,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20];
  	char hex[41];
  
+	git_set_appname("git-ssh-upload");
+
  	prog = getenv(COUNTERPART_ENV_NAME);
  	if (!prog) prog = COUNTERPART_PROGRAM_NAME;
  
diff --git a/stripspace.c b/stripspace.c
index 65a6346..95c2e43 100644
--- a/stripspace.c
+++ b/stripspace.c
@@ -34,6 +34,8 @@ int main(int argc, char **argv)
  	int incomplete = 0;
  	char line[1024];
  
+	git_set_appname("git-stripspace");
+
  	while (fgets(line, sizeof(line), stdin)) {
  		incomplete = cleanup(line);
  
diff --git a/symbolic-ref.c b/symbolic-ref.c
index 193c87c..a8b3b9d 100644
--- a/symbolic-ref.c
+++ b/symbolic-ref.c
@@ -19,6 +19,8 @@ static void check_symref(const char *HEA
  
  int main(int argc, const char **argv)
  {
+	git_set_appname("git-symbolic-ref");
+
  	setup_git_directory();
  	git_config(git_default_config);
  	switch (argc) {
diff --git a/tar-tree.c b/tar-tree.c
index fc60a90..7a388f5 100644
--- a/tar-tree.c
+++ b/tar-tree.c
@@ -26,9 +26,9 @@ static void reliable_write(void *buf, un
  		if (ret < 0) {
  			if (errno == EPIPE)
  				exit(0);
-			die("git-tar-tree: %s", strerror(errno));
+			die("%s", strerror(errno));
  		} else if (!ret) {
-			die("git-tar-tree: disk full?");
+			die("disk full?");
  		}
  		size -= ret;
  		buf += ret;
@@ -308,6 +308,8 @@ int main(int argc, char **argv)
  	struct tree_desc tree;
  	struct strbuf current_path;
  
+	git_set_appname("git-tar-tree");
+
  	current_path.buf = xmalloc(PATH_MAX);
  	current_path.alloc = PATH_MAX;
  	current_path.len = current_path.eof = 0;
diff --git a/test-date.c b/test-date.c
index 93e8027..3d2cfbb 100644
--- a/test-date.c
+++ b/test-date.c
@@ -7,6 +7,8 @@ int main(int argc, char **argv)
  {
  	int i;
  
+	git_set_appname("git-test-date");
+
  	for (i = 1; i < argc; i++) {
  		char result[100];
  		time_t t;
diff --git a/test-delta.c b/test-delta.c
index 1be8ee0..bf6c6ac 100644
--- a/test-delta.c
+++ b/test-delta.c
@@ -27,6 +27,8 @@ int main(int argc, char *argv[])
  	void *from_buf, *data_buf, *out_buf;
  	unsigned long from_size, data_size, out_size;
  
+	git_set_appname("git-test-delta");
+
  	if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) {
  		fprintf(stderr, "Usage: %s\n", usage);
  		return 1;
diff --git a/tree-diff.c b/tree-diff.c
index 1cdf8aa..5170ddf 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -191,7 +191,7 @@ int diff_tree(struct tree_desc *t1, stru
  			update_tree_entry(t2);
  			continue;
  		}
-		die("git-diff-tree: internal error");
+		die("internal error");
  	}
  	return 0;
  }
diff --git a/unpack-file.c b/unpack-file.c
index 23a8562..a49e230 100644
--- a/unpack-file.c
+++ b/unpack-file.c
@@ -27,6 +27,8 @@ int main(int argc, char **argv)
  {
  	unsigned char sha1[20];
  
+	git_set_appname("git-unpack-file");
+
  	if (argc != 2 || get_sha1(argv[1], sha1))
  		usage("git-unpack-file <sha1>");
  
diff --git a/unpack-objects.c b/unpack-objects.c
index 3b824b0..315ea67 100644
--- a/unpack-objects.c
+++ b/unpack-objects.c
@@ -270,6 +270,8 @@ int main(int argc, char **argv)
  	int i;
  	unsigned char sha1[20];
  
+	git_set_appname("git-unpack-objects");
+
  	setup_git_directory();
  
  	quiet = !isatty(2);
diff --git a/update-index.c b/update-index.c
index facec8d..f8e24d4 100644
--- a/update-index.c
+++ b/update-index.c
@@ -354,7 +354,7 @@ static void chmod_path(int flip, const c
  	report("chmod %cx '%s'", flip, path);
  	return;
   fail:
-	die("git-update-index: cannot chmod %cx '%s'", flip, path);
+	die("cannot chmod %cx '%s'", flip, path);
  }
  
  static struct cache_file cache_file;
@@ -374,7 +374,7 @@ static void update_one(const char *path,
  
  	if (force_remove) {
  		if (remove_file_from_cache(p))
-			die("git-update-index: unable to remove %s", path);
+			die("unable to remove %s", path);
  		report("remove '%s'", path);
  		return;
  	}
@@ -450,8 +450,7 @@ static void read_index_info(int line_ter
  		if (!mode) {
  			/* mode == 0 means there is no such path -- remove */
  			if (remove_file_from_cache(path_name))
-				die("git-update-index: unable to remove %s",
-				    ptr);
+				die("unable to remove %s", ptr);
  		}
  		else {
  			/* mode ' ' sha1 '\t' name
@@ -460,8 +459,7 @@ static void read_index_info(int line_ter
  			 */
  			ptr[-42] = ptr[-1] = 0;
  			if (add_cacheinfo(mode, sha1, path_name, stage))
-				die("git-update-index: unable to update %s",
-				    path_name);
+				die("unable to update %s", path_name);
  		}
  		if (path_name != ptr)
  			free(path_name);
@@ -598,12 +596,17 @@ int main(int argc, const char **argv)
  	int i, newfd, entries, has_errors = 0, line_termination = '\n';
  	int allow_options = 1;
  	int read_from_stdin = 0;
-	const char *prefix = setup_git_directory();
-	int prefix_length = prefix ? strlen(prefix) : 0;
+	const char *prefix;
+	int prefix_length;
  	char set_executable_bit = 0;
  
+	git_set_appname("git-update-index");
+
  	git_config(git_default_config);
  
+	prefix = setup_git_directory();
+	prefix_length = prefix ? strlen(prefix) : 0;
+
  	newfd = hold_index_file_for_update(&cache_file, get_index_file());
  	if (newfd < 0)
  		die("unable to create new cachefile");
@@ -653,20 +656,19 @@ int main(int argc, const char **argv)
  				unsigned int mode;
  
  				if (i+3 >= argc)
-					die("git-update-index: --cacheinfo <mode> <sha1> <path>");
+					die("--cacheinfo <mode> <sha1> <path>");
  
  				if ((sscanf(argv[i+1], "%o", &mode) != 1) ||
  				    get_sha1_hex(argv[i+2], sha1) ||
  				    add_cacheinfo(mode, sha1, argv[i+3], 0))
-					die("git-update-index: --cacheinfo"
-					    " cannot add %s", argv[i+3]);
+					die("--cacheinfo cannot add %s", argv[i+3]);
  				i += 3;
  				continue;
  			}
  			if (!strcmp(path, "--chmod=-x") ||
  			    !strcmp(path, "--chmod=+x")) {
  				if (argc <= i+1)
-					die("git-update-index: %s <path>", path);
+					die("%s <path>", path);
  				set_executable_bit = path[8];
  				continue;
  			}
diff --git a/update-ref.c b/update-ref.c
index ba4bf51..1fd32d1 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -24,6 +24,8 @@ int main(int argc, char **argv)
  	unsigned char sha1[20], oldsha1[20], currsha1[20];
  	int fd, written;
  
+	git_set_appname("git-update-ref");
+
  	setup_git_directory();
  	git_config(git_default_config);
  	if (argc < 3 || argc > 4)
diff --git a/update-server-info.c b/update-server-info.c
index 0b6c383..3496d0e 100644
--- a/update-server-info.c
+++ b/update-server-info.c
@@ -7,6 +7,9 @@ int main(int ac, char **av)
  {
  	int i;
  	int force = 0;
+
+	git_set_appname("git-update-server-info");
+
  	for (i = 1; i < ac; i++) {
  		if (av[i][0] == '-') {
  			if (!strcmp("--force", av[i]) ||
diff --git a/upload-pack.c b/upload-pack.c
index 47560c9..ed16b53 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -38,10 +38,10 @@ static void create_pack_file(void)
  	int create_full_pack = (nr_our_refs == nr_needs && !nr_has);
  
  	if (pipe(fd) < 0)
-		die("git-upload-pack: unable to create pipe");
+		die("unable to create pipe");
  	pid = fork();
  	if (pid < 0)
-		die("git-upload-pack: unable to fork git-rev-list");
+		die("unable to fork git-rev-list");
  
  	if (!pid) {
  		int i;
@@ -84,19 +84,19 @@ static void create_pack_file(void)
  			}
  		*p++ = NULL;
  		execv_git_cmd(argv);
-		die("git-upload-pack: unable to exec git-rev-list");
+		die("unable to exec git-rev-list");
  	}
  	dup2(fd[0], 0);
  	close(fd[0]);
  	close(fd[1]);
  	execl_git_cmd("pack-objects", "--stdout", NULL);
-	die("git-upload-pack: unable to exec git-pack-objects");
+	die("unable to exec git-pack-objects");
  }
  
  static int got_sha1(char *hex, unsigned char *sha1)
  {
  	if (get_sha1_hex(hex, sha1))
-		die("git-upload-pack: expected SHA1 object, got '%s'", hex);
+		die("expected SHA1 object, got '%s'", hex);
  	if (!has_sha1_file(sha1))
  		return 0;
  	if (nr_has < MAX_HAS) {
@@ -162,7 +162,7 @@ static int get_common_commits(void)
  			packet_write(1, "NAK\n");
  			return -1;
  		}
-		die("git-upload-pack: expected SHA1 list, got '%s'", line);
+		die("expected SHA1 list, got '%s'", line);
  	}
  }
  
@@ -191,8 +191,7 @@ static int receive_needs(void)
  			sha1_buf = needs_sha1[needs];
  
  		if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf))
-			die("git-upload-pack: protocol error, "
-			    "expected to get sha, not '%s'", line);
+			die("protocol error, expected to get sha, not '%s'", line);
  		if (strstr(line+45, "multi_ack"))
  			multi_ack = 1;
  		if (strstr(line+45, "thin-pack"))
@@ -208,7 +207,7 @@ static int receive_needs(void)
  		 */
  		o = lookup_object(sha1_buf);
  		if (!o || !(o->flags & OUR_REF))
-			die("git-upload-pack: not our ref %s", line+5);
+			die("not our ref %s", line+5);
  		if (!(o->flags & WANTED)) {
  			o->flags |= WANTED;
  			needs++;
@@ -222,7 +221,7 @@ static int send_ref(const char *refname,
  	struct object *o = parse_object(sha1);
  
  	if (!o)
-		die("git-upload-pack: cannot find object %s:", sha1_to_hex(sha1));
+		die("cannot find object %s:", sha1_to_hex(sha1));
  
  	if (capabilities)
  		packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
@@ -261,6 +260,8 @@ int main(int argc, char **argv)
  	int i;
  	int strict = 0;
  
+	git_set_appname("git-upload-pack");
+
  	for (i = 1; i < argc; i++) {
  		char *arg = argv[i];
  
diff --git a/usage.c b/usage.c
index 1fa924c..bb89d66 100644
--- a/usage.c
+++ b/usage.c
@@ -5,8 +5,11 @@
   */
  #include "git-compat-util.h"
  
+static char appname[32+3]="";      /* +3 for ': \0' */
+
  static void report(const char *prefix, const char *err, va_list params)
  {
+	fputs(appname[0]?appname:"",stderr);
  	fputs(prefix, stderr);
  	vfprintf(stderr, err, params);
  	fputs("\n", stderr);
@@ -37,3 +40,14 @@ int error(const char *err, ...)
  	va_end(params);
  	return -1;
  }
+
+void git_set_appname(const char *name)
+{
+	size_t len=(name && *name)?strlen(name):0;
+	if (0==len)
+		return;
+	memcpy(appname,name,len>sizeof(appname)-3?sizeof(appname)-3:len);
+	appname[len++]=':';
+	appname[len++]=' ';
+	appname[len++]='\0';
+}
diff --git a/var.c b/var.c
index a57a33b..a816373 100644
--- a/var.c
+++ b/var.c
@@ -54,6 +54,9 @@ static int show_config(const char *var, 
  int main(int argc, char **argv)
  {
  	const char *val;
+
+	git_set_appname("git-var");
+
  	if (argc != 2) {
  		usage(var_usage);
  	}
diff --git a/verify-pack.c b/verify-pack.c
index c99db9d..e1b3b01 100644
--- a/verify-pack.c
+++ b/verify-pack.c
@@ -35,6 +35,8 @@ int main(int ac, char **av)
  	int verbose = 0;
  	int no_more_options = 0;
  
+	git_set_appname("git-verify-pack");
+
  	while (1 < ac) {
  		char path[PATH_MAX];
  
diff --git a/write-tree.c b/write-tree.c
index dcad6e6..9f68fda 100644
--- a/write-tree.c
+++ b/write-tree.c
@@ -92,6 +92,8 @@ int main(int argc, char **argv)
  	int entries;
  	unsigned char sha1[20];
  	
+	git_set_appname("git-write-tree");
+
  	setup_git_directory();
  
  	entries = read_cache();
@@ -106,7 +108,7 @@ int main(int argc, char **argv)
  		die("too many options");
  
  	if (entries < 0)
-		die("git-write-tree: error reading cache");
+		die("error reading cache");
  
  	/* Verify that the tree is merged */
  	funny = 0;
@@ -121,7 +123,7 @@ int main(int argc, char **argv)
  		}
  	}
  	if (funny)
-		die("git-write-tree: not able to write tree");
+		die("not able to write tree");
  
  	/* Also verify that the cache does not have path and path/file
  	 * at the same time.  At this point we know the cache has only
@@ -148,11 +150,11 @@ int main(int argc, char **argv)
  		}
  	}
  	if (funny)
-		die("git-write-tree: not able to write tree");
+		die("not able to write tree");
  
  	/* Ok, write it out */
  	if (write_tree(active_cache, entries, "", 0, sha1) != entries)
-		die("git-write-tree: internal error");
+		die("internal error");
  	printf("%s\n", sha1_to_hex(sha1));
  	return 0;
  }
-- 
1.3.0.g36932-dirty

^ permalink raw reply related

* Re: [PATCH] Make die() and error() prefix line with binary name if set
From: Rocco Rutte @ 2006-04-25 14:13 UTC (permalink / raw)
  To: git
In-Reply-To: <e2kt7h$o4a$1@sea.gmane.org>

* Jakub Narebski <jnareb@gmail.com>:

>Wouldn't it be easier (and less idiomatic) to just do

Oh, thanks for pointing it out. The second one I sent fixes it (and is 
against an updated master branch).

   bye, Rocco
-- 
:wq!

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links
From: Linus Torvalds @ 2006-04-25 15:10 UTC (permalink / raw)
  To: Sam Vilain; +Cc: git
In-Reply-To: <20060425035421.18382.51677.stgit@localhost.localdomain>



On Tue, 25 Apr 2006, Sam Vilain wrote:
>
> This patch series implements "prior" links in commit objects.  A
> 'prior' link on a commit represents its historical precedent, as
> opposed to the previous commit(s) that this commit builds upon.

I really don't think this is worth it.

We already have a very useful notion of "prior" commit that is used daily 
(well, weekly) for the Linux kernel, and it's used for one of the few 
places where this really makes unequivocal sense. "git revert".

It's also implemented in the only way that has clear and unambiguous 
semantics: by putting the prior link into the free-form part. The reason 
this is clear and unambiguous is that it makes it clear that it has no 
actual technical impact on any serious git strategy, ie there is never any 
question of "What does it _mean_?".

At the same time, it gives exactly what you actually _want_ for a prior 
link: it makes it easy to look up the commit that was replaced, or fixed, 
or that is related, or just any random semantics that you can explain 
easily in the text.

Both gitk and qgit already support it, and it's trivially 
cut-and-pasteable from any log message to see what it is when you work on 
the command line too.

In contrast, adding a new header is serious trouble:

 - What does it _mean_ from a technical angle? 

   Does it matter for merging? One of your patches seems to make it so, 
   which is _really_ confusing. Why should it? And does it affect anything 
   else that git does?

   Does "prior" have any meaning for "git-fsck-objects" and/or for object 
   pruning? For "git fetch/pull"?

 - What does it mean from a semantic standpoint?

   Is "prior" a note that something was reverted? Fixed? Changed? 
   Cherry-picked? And if it is Cherry-picked, than I would flat-out refuse 
   to ever merge with a tree that has it, because it pretty much by 
   definition means that the object that "prior" points to simply doesn't 
   _exist_ in my tree (since it was cherry-picked from somebody elses 
   tree). Or that it means that my history got tangled up with the history 
   of the failed branch that needed cherry-picking to clean up..

 - You say that there is just one "prior" parent, but why just one? 
   There's no way to even _think_ about this, since it seems to have no 
   actual semantic meaning.

I think all the problems really boil down to "What does this mean?"

Without an answer to that question, it's just a random feature. It's 
something that you can use and mis-use, but that has no "meaning". It only 
has whatever meaning you personally assign to it, but that implies that 
git shouldn't parse it, and shouldn't care about it.

Which again says that it should act like the current free-form thing does 
so well - it has no meaning, but it allows easy lookups.

		Linus

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Linus Torvalds @ 2006-04-25 15:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, jnareb
In-Reply-To: <7v7j5e2jv7.fsf@assigned-by-dhcp.cox.net>



On Tue, 25 Apr 2006, Junio C Hamano wrote:
> 
> How about an ability to "attach" arbitrary objects to commit
> objects?  The commit object would look like:
> 
>     tree 0aaa3fecff73ab428999cb9156f8abc075516abe
>     parent 5a6a8c0e012137a3f0059be40ec7b2f4aa614355
>     parent e1cbc46d12a0524fd5e710cbfaf3f178fc3da504
>     related a0e7d36193b96f552073558acf5fcc1f10528917 key
>     related 0032d548db56eac9ea09b4ba05843365f6325b85 cherrypick

This would at the face of it seem a bit better, but the fact is, it's not.

Without _semantics_ for the different cases, it's just random crud.

What does any of the fields _mean_ to git? In particular, if you cannot 
come up with an _exact_ definition of what they mean for fsck, pull, push, 
and any other random thing (how to show them for logging? How do they 
affect merge bases?), then it's still just random free-form text, and it 
should go into the random free-form section.

> The semantics I would attach to these "related" links are as
> follows:
> 
>  * To the "core" level git, they do not mean anything other than
>    "you must to have these objects, and objects reachable from
>    them, if you are going to have this commit and claim your
>    repository is without missing objects".

Ok, a real semantic meaning. However:

THAT IS COMPLETELY USELESS.

It sure isn't useful for cherry-picking, which so far is one of the only 
"real examples" of where this would actually be used. 

It isn't useful for much anything else either, because you really have two 
cases:

 - the "related" commit is an indirect parent _anyway_ (for things like 
   "revert", this would obviously be the case, since it doesn't generally 
   make a lot of sense to revert something that has never touched your 
   history). In this case, the git semantics end up being NULL, and you 
   just have another relationship that doesn't actually add any new 
   information to the tree.

 - the "related" commit is not actually in the set of _real_ parenthood at 
   all, and actually points to a different branch (or possibly even 
   different project).

   This case I'd sure as hell hate to have for the kernel, at least. I 
   would have to add crap to my workflow to make sure that people do _not_ 
   have these kinds of linkages that link in random parts of their project 
   that doesn't actually have anything to do with the history I'm pulling.

Those are the only two possible cases. Either it's an indirect parent, or 
it isn't. Neither one makes any sense: the first one is a no-op from your 
semantic definition, and the second one is just crazy and you'll just find 
that people have to protect themselves from other developers doing 
something crazy by mistake.

I want the git objects to have clear and unambiguous semantics. I want 
people to be able to explain exactly what the fields _mean_. No "this 
random field could be used this random way" crud, please.

			Linus

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Linus Torvalds @ 2006-04-25 15:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, jnareb
In-Reply-To: <Pine.LNX.4.64.0604250811230.3701@g5.osdl.org>



On Tue, 25 Apr 2006, Linus Torvalds wrote:
> 
> I want the git objects to have clear and unambiguous semantics. I want 
> people to be able to explain exactly what the fields _mean_. No "this 
> random field could be used this random way" crud, please.

Btw, if the whole point is a "leave random porcelain a field that they can 
use any way they want", then I say "Hell NO!".

Random porcelain can already just maintain their own lists of "related" 
stuff, any way they want: you can keep it in a file in ".git/porcelain", 
called "list-commit-relationships", or you could use a git blob for it and 
have a reference to it in .git/refs/porcelain/relationships or whatever. 

If it has no clear and real semantic meaning for core git, then it 
shouldn't be in the core git objects.

The absolute last thing we want is a "random out" that starts to mean 
different things to different people, groups and porcelains.

That's just crazy, and it's how you end up with a backwards compatibility 
mess five years from now that is totally unresolvable, because different 
projects end up having different meanings or uses for the fields, so 
converting the database (if we ever find a better format, or somebody 
notices that SHA1 can be broken by a five-year-old-with-a-crayon).

There's a reason "minimalist" actually ends up _working_. I'll take a UNIX 
"system calls have meanings" approach over a Windows "there's fifteen 
different flavors of 'open()', and we also support magic filenames with 
specific meaning" kind of thing.

			Linus

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: sean @ 2006-04-25 16:17 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: junkio, git, jnareb
In-Reply-To: <Pine.LNX.4.64.0604250833540.3701@g5.osdl.org>

On Tue, 25 Apr 2006 08:40:25 -0700 (PDT)
Linus Torvalds <torvalds@osdl.org> wrote:

> On Tue, 25 Apr 2006, Linus Torvalds wrote:
> > 
> > I want the git objects to have clear and unambiguous semantics. I want 
> > people to be able to explain exactly what the fields _mean_. No "this 
> > random field could be used this random way" crud, please.
> 
> Btw, if the whole point is a "leave random porcelain a field that they can 
> use any way they want", then I say "Hell NO!".
> 
> Random porcelain can already just maintain their own lists of "related" 
> stuff, any way they want: you can keep it in a file in ".git/porcelain", 
> called "list-commit-relationships", or you could use a git blob for it and 
> have a reference to it in .git/refs/porcelain/relationships or whatever. 
> 
> If it has no clear and real semantic meaning for core git, then it 
> shouldn't be in the core git objects.
> 
> The absolute last thing we want is a "random out" that starts to mean 
> different things to different people, groups and porcelains.
> 
> That's just crazy, and it's how you end up with a backwards compatibility 
> mess five years from now that is totally unresolvable, because different 
> projects end up having different meanings or uses for the fields, so 
> converting the database (if we ever find a better format, or somebody 
> notices that SHA1 can be broken by a five-year-old-with-a-crayon).
> 
> There's a reason "minimalist" actually ends up _working_. I'll take a UNIX 
> "system calls have meanings" approach over a Windows "there's fifteen 
> different flavors of 'open()', and we also support magic filenames with 
> specific meaning" kind of thing.
> 

It's a fair point.  But adding a separate database to augment the core 
information has some downsides.  That is, that information isn't pulled, 
cloned, or pushed automatically; it doesn't get to ride for free on top 
of the core.

Accommodating extra git headers (or "note"'s in Junio's example) would allow
a developer to record the fact that he is integrating a patch taken 
from a commit in the devel branch and backporting it to the release 
branch.   Either by adding a note that references the bug tracking #, or 
a commit sha1 from the devel branch that is already associated with the bug.

Of course that information could be embedded in the free text area, but 
you yourself have argued vigorously that it is brain damaged to try and rely
on parsing free form text for these types of situations.  Most of the potential 
uses aren't really meant for a human to read while looking at the log anyway, 
they just get in the way.  Another option that you alluded to, was to 
stuff the information in another git object.   But such an object would have 
to embed a reference to the original commit, thus you haven't really made 
changing the SHA1 algorithm any easier.  And then you also then have to jump 
through hoops to make sure that you pull the proper extra blobs that contain 
information about the real commits you just pulled.

But if the information is in the actual commit header it gets to tag along
for free with never any worry it will be separated from the commit in question.
So when the developer above updates his official repo the bug tracker system 
can notice that the bug referenced in its system has had a patch backported 
and take whatever action is desired.  

Of course there are other ways to do this, but integrating it into git means it
gets a free ride on the core, and it shouldn't really get in the way of core 
any more than email X- headers get in the way of email flowing.

Sean

^ permalink raw reply

* Re: [RFC] [PATCH 0/5] Implement 'prior' commit object links (and other commit links ideas)
From: Jakub Narebski @ 2006-04-25 16:27 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.64.0604250833540.3701@g5.osdl.org>

Linus Torvalds wrote:

> On Tue, 25 Apr 2006, Linus Torvalds wrote:
>> 
>> I want the git objects to have clear and unambiguous semantics. I want
>> people to be able to explain exactly what the fields _mean_. No "this
>> random field could be used this random way" crud, please.
> 
> Btw, if the whole point is a "leave random porcelain a field that they can
> use any way they want", then I say "Hell NO!".

The generic commit links "related" which is fsck-able at least and "note"
which is not. It is idea somewhat on the level of providing _extended
attributes_ in VFS in Linux kernel, IMVHO.

"note" can be considere cruft, "related" is fsck-able and pull-able so has
meaning for core (even if not all "note" and/or "related" links have any
repercussion for merging for example).

So far there are following core git ideas of using this feature (akin to
using extended attributes for ACL, or SELinux properties):

1. "related" link "bind" for better support of subprojects. Useful if some
parts of project are developed independently (e.g. lm_sensors or ALSA was
in Linux kernel, xdiff for git, somelibrary or somemodule for someproject
etc.).
2. "note" link "cherrypicked" for cherry-picking, rebase etc., for example
to not apply the same commit twice. Useful in merging after cherry picking.

Additionally there are following less certain ideas

3. "prior" link in the sense of prior state of frequently rebased branch
like git's "pu" (case (1) in first post in this thread)
4. "depend" link for creating darc-esque dependency partial ordering of
commits (patches), for better merge perhaps
5. "note" link "rename" (or more generic "contents related") for remembering
renames/file moving, file splitting, contents moving and copying, including
correcting automatic "rename" detection at merge (i.e. remembering false
positives and false negatives). Useful in subsequent merges and information
commands (log, whatchanged, annotate/blame, diff).
6. "note" link "origin" to remember for where the commit was pulled.

Note that none of those are non-core Porcelain ideas.

-- 
Jakub Narebski
Warsaw, Poland

^ 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