Git development
 help / color / mirror / Atom feed
* (unknown), 
From: Francesco Pretto @ 2007-11-01 20:44 UTC (permalink / raw)
  To: git

subscribe git

^ permalink raw reply

* Re: [PATCH] Make git-clone obey "--" (end argument parsing)
From: Junio C Hamano @ 2007-11-01 20:39 UTC (permalink / raw)
  To: Heikki Orsila; +Cc: git
In-Reply-To: <20071101195418.607DA4F95F@jolt.modeemi.cs.tut.fi>

shd@jolt.modeemi.cs.tut.fi (Heikki Orsila) writes:

> Oops. Reposting the patch.
>
> This patch handles "--" argument for git-clone.
>
> Signed-off-by: Heikki Orsila <heikki.orsila@iki.fi>
>
>>From bd2d661c565062eacc80dda90f3978303308f9bb Mon Sep 17 00:00:00 2001
> From: Heikki Orsila <heikki.orsila@iki.fi>
> Date: Thu, 1 Nov 2007 16:21:39 +0200
> Subject: [PATCH] Make git-clone obey "--" (end argument parsing)
>
> ---
>  Documentation/git-clone.txt |    2 +-
>  git-clone.sh                |    5 ++++-
>  2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
> index 253f4f0..7fdcd42 100644
> --- a/Documentation/git-clone.txt
> +++ b/Documentation/git-clone.txt
> @@ -12,7 +12,7 @@ SYNOPSIS
>  'git-clone' [--template=<template_directory>]
>  	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
>  	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
> -	  [--depth <depth>] <repository> [<directory>]
> +	  [--depth <depth>] [--] <repository> [<directory>]

I do not think this breaks anything, but does it _help_
anything in practice?

What kind of breakage does this patch fix?

^ permalink raw reply

* Re: [PATCH] Implement git commit as a builtin command.
From: Junio C Hamano @ 2007-11-01 20:30 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: git
In-Reply-To: <1193944163-22892-1-git-send-email-krh@redhat.com>

Kristian Høgsberg <krh@redhat.com> writes:

> Move git-commit.sh to contrib/examples.
>
> Signed-off-by: Kristian Høgsberg <krh@redhat.com>
> ---
>
> Here's the builtin-commit patch again, this time updated to build
> against the in-tree strbuf and option parser.  Now that Pierre has
> done all the work of getting those pieces upstream, I notice that the
> C version ends up 20 lines shorter than the shell script :)
>
> There's a couple of changes to the test suite at the end, which
> removes some EDITOR=: VISUAL=: hard-coding in a few tests and then
> sets the default editor to /bin/true.  This is to address the problem
> that the C version of launch editor doesn't support any kind of shell
> qouting or built-ins.  Should we just use system(3) here?

I do not care much about _how_ it is done, but one of the most
often typed command in my .history is

	EDITOR=: git commit

I'd be somewhat unhappy to be forced to retrain my fingers ;-)

^ permalink raw reply

* Re: What's cooking in git.git (topics)
From: Junio C Hamano @ 2007-11-01 20:27 UTC (permalink / raw)
  To: Geert Bosch; +Cc: Linus Torvalds, git
In-Reply-To: <916BE4AD-5BD9-48E6-8026-B1AC7387E28D@adacore.com>

Geert Bosch <bosch@adacore.com> writes:

> I often type "make clean" as well many "git xyz" commands
> during development, and so it happens that at times, I type
> "git clean" by accident.

Happened to me once.  I hate that command.

> So, I propose *not* converting git clean to a C builtin,
> but instead adding --untracked and --ignored options to
> git-rm.

I think what you are trying to do is to deprecate or remove "git
clean".

I do not know where "git clean" came from.  I am suspecting that
it was to give counterparts to some other SCMs, but do not know
which ones.  Some people wanted to have it --- so you need to
convince them that it is a bad idea first.  Adding an equivalent
options to "git rm" alone does not solve that issue.

^ permalink raw reply

* Re: Newbie: report of first experience with git-rebase.
From: Junio C Hamano @ 2007-11-01 20:20 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Johannes Schindelin, Sergei Organov, git
In-Reply-To: <20071101151016.GA26103@fieldses.org>

"J. Bruce Fields" <bfields@fieldses.org> writes:

> On Thu, Nov 01, 2007 at 02:24:37PM +0000, Johannes Schindelin wrote:
>> 
>> They are rare events.  In your case I guess that subtly different versions 
>> were _actually_ applied (such as white space fixes),
>
> That's actually pretty common, in my experience.
>
>> which is why such a rare event hit you.
>
> I'm using git to track some changes I submitted to a project that's
> mainly text, and that I only get release tarballs of.  On my most recent
> rebase all my patches got applied, but the text also got re-wrapped and
> re-indented at the same time.  So all but I think one or two of a dozen
> patches ended up with a conflict resolution and then --skip.
>
> Which may not be a case git's really intended for--fair enough.  But
> I've found it's pretty common in my kernel work too.  Either I'm
> rebasing against changes I made myself, or else a maintainer took my
> changes but fixed up some minor style problems along the way.

Ok, so I retract that "rare" comment.

Now, we have established that this is a real problem worth
solving, what's next?

^ permalink raw reply

* Re: [PATCH 10/10] push: teach push to be quiet if local ref is strict subset of remote ref
From: Junio C Hamano @ 2007-11-01 20:18 UTC (permalink / raw)
  To: Steffen Prohaska; +Cc: Andreas Ericsson, git
In-Reply-To: <3550D197-CA8C-4B06-9A95-3C7F18EBEFA7@zib.de>

Steffen Prohaska <prohaska@zib.de> writes:

> On Nov 1, 2007, at 10:11 AM, Andreas Ericsson wrote:
>
>> Steffen Prohaska wrote:
>>
>>> You're forced to do the integration immediately.

The context of this "forced" is that you say (in the following
paragraph) the user's main objective was to "push", but I do not
think "to push" is ever the main objective.

 - If it is to give integrated result for others to work further
   on, then you need to resolve before being able to achieve
   that goal.  There is no escaping from it.

 - On the other hand, if it is to show what you did as early as
   possible in a working shape, and if the updated shared
   repository has changes from somebody else that conflicts you,
   in a CVS/SVN style shared workflow, there is no way for you
   to show what you did in isolation.  If you try to follow that
   model in git and insist pushing to the same branch, then you
   are forced to resolve first.

   But you do not have to.  You could push out to another new
   branch, and say "Here is how you could do it, although this
   is based on an older codebase and conflicts with what
   recently happened to the tip".  You could even ask other
   party whose changes conflict with yours to help with the
   merge by saying "I pushed it out, you are more familiar with
   that area of the code and with your changes near the tip of
   the trunk, so could you merge it and push out the result?"

>> Yes, but you get to choose how. Perhaps git-push should list more
>> options than just git-pull, such as the three commands required to
>> rebase the currently checked out branch onto its remote counterpart.
>> That would support more workflows.
>
> I agree. Providing better hints would be good.

I am not so sure about that.  If there are three different
workflows, should git-push give hints suitable for all of them?

The current hint was added in response to users' requests, and I
think it could be generalized.  What we would want the end user
to realize is:

    What I tried to push out is stale, I do not want to push out
    something that does not contain what the other side has
    done, so I need to integrate my work with what the other
    side have before pushing to that branch at the remote.

    In my workflow, that means doing rebase of the branch I
    tried to push out on top of the remote branch I was trying
    to push to.

The second paragraph depends on the workflow.  Do we want to
(can we afford the space to) give a laundry list here?  Probably
not.

>>> Your main objective was to push, but the shared workflow forces
>>> you to do the integration _now_ (by using pull). In a pull-only
>>> workflow, you can just push and defer the integration for later.
>>
>> No, you can also fetch + rebase.
>
> Right. My point was than one cannot defer the integration. It
> must be addressed immediately.

See above.

>>> Some people claim fetch + rebase is superior to fetch + merge.
>>> The only point I can see is that fetch + rebase gives a linear
>>> history without loops, which is nicer to visualize. I recently
>>> asked on the list if there are any benefits of fetch + rebase
>>> over fetch + merge, besides a nicer visualization.
>>
>>
>> It's easier to bisect...
>> With a mostly linear history, this problem goes away.
>
> This is really an interesting point. I did not start to use
> git bisect regularly. But I certainly plan to do so in the future.
>
> Couldn't bisect learn to better cope with non-linear history?

It copes with it as best as it can.

Another thing to think about is how "everybody fetches, merges
and pushes out" would interact with the concept of "mainline".
Strictly speaking, the point of distributed development is that
there is no mainline, but workflows based on "fetch + rebase"
allows --first-parent to give a reasonable approximation of what
people would naively expect how the mainline would look like.
If everybody fetches, merges and pushes out, there is no
"mainline" and --first-parent would give totally useless
history.

^ permalink raw reply

* Re: [PATCH] Implement git commit as a builtin command.
From: Jakub Narebski @ 2007-11-01 20:14 UTC (permalink / raw)
  To: git
In-Reply-To: <1193944163-22892-1-git-send-email-krh@redhat.com>

Kristian H?gsberg wrote:

> Move git-commit.sh to contrib/examples.

Just a note: you might want to use "git format-patch -M".

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* [PATCH] Make git-clone obey "--" (end argument parsing)
From: Heikki Orsila @ 2007-11-01 19:54 UTC (permalink / raw)
  To: git

Oops. Reposting the patch.

This patch handles "--" argument for git-clone.

Signed-off-by: Heikki Orsila <heikki.orsila@iki.fi>

>From bd2d661c565062eacc80dda90f3978303308f9bb Mon Sep 17 00:00:00 2001
From: Heikki Orsila <heikki.orsila@iki.fi>
Date: Thu, 1 Nov 2007 16:21:39 +0200
Subject: [PATCH] Make git-clone obey "--" (end argument parsing)

---
 Documentation/git-clone.txt |    2 +-
 git-clone.sh                |    5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 253f4f0..7fdcd42 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -12,7 +12,7 @@ SYNOPSIS
 'git-clone' [--template=<template_directory>]
 	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
 	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
-	  [--depth <depth>] <repository> [<directory>]
+	  [--depth <depth>] [--] <repository> [<directory>]
 
 DESCRIPTION
 -----------
diff --git a/git-clone.sh b/git-clone.sh
index 0ea3c24..3f00693 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -14,7 +14,7 @@ die() {
 }
 
 usage() {
-	die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]"
+	die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] [--] <repo> [<dir>]"
 }
 
 get_repo_base() {
@@ -160,6 +160,9 @@ while
 	*,--depth)
 		shift
 		depth="--depth=$1";;
+	*,--)
+		shift
+		break ;;
 	*,-*) usage ;;
 	*) break ;;
 	esac
-- 
1.5.3.4.498.g9c514-dirty

^ permalink raw reply related

* Re: [PATCH] git-rev-list.txt: rev stands for revision, not reverse.
From: Junio C Hamano @ 2007-11-01 19:51 UTC (permalink / raw)
  To: Ralf Wildenhues; +Cc: git
In-Reply-To: <20071101084552.GA4934@ins.uni-bonn.de>

Ralf Wildenhues <Ralf.Wildenhues@gmx.de> writes:

> Mention revs, revisions as aliases for commit objects,
> to clarify that rev-list is not an abbreviation for
> listing in reverse order, but for listing revisions.
> ---
> Yes, believe it or not, but I stumbled over the synopsis
>
> | git-rev-list - Lists commit objects in reverse chronological order
>
> asking myself whether rev could possibly mean "reverse".
> I hope this helps avoid this pitfall for others.

In addition to your patch,

	git-rev-list - List commits from most recent to older

might be a good rewording?  "rev-list --reverse" reverses that
usual order and we end up explaining double reversal if we use
the phrase "reverse chronological order" to describe the normal
order.

^ permalink raw reply

* [PATCH] Implement git commit as a builtin command.
From: Kristian Høgsberg @ 2007-11-01 19:09 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Kristian Høgsberg

Move git-commit.sh to contrib/examples.

Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---

Here's the builtin-commit patch again, this time updated to build
against the in-tree strbuf and option parser.  Now that Pierre has
done all the work of getting those pieces upstream, I notice that the
C version ends up 20 lines shorter than the shell script :)

There's a couple of changes to the test suite at the end, which
removes some EDITOR=: VISUAL=: hard-coding in a few tests and then
sets the default editor to /bin/true.  This is to address the problem
that the C version of launch editor doesn't support any kind of shell
qouting or built-ins.  Should we just use system(3) here?

cheers,
Kristian

 Makefile                       |    9 +-
 builtin-commit.c               |  608 ++++++++++++++++++++++++++++++++++++++
 builtin-tag.c                  |    2 +-
 builtin.h                      |    3 +-
 contrib/examples/git-commit.sh |  628 ++++++++++++++++++++++++++++++++++++++++
 git-commit.sh                  |  628 ----------------------------------------
 git.c                          |    3 +-
 strbuf.h                       |    1 +
 t/t3501-revert-cherry-pick.sh  |    4 +-
 t/t3901-i18n-patch.sh          |    8 +-
 t/test-lib.sh                  |    4 +-
 11 files changed, 1253 insertions(+), 645 deletions(-)
 create mode 100644 builtin-commit.c
 create mode 100755 contrib/examples/git-commit.sh
 delete mode 100755 git-commit.sh

diff --git a/Makefile b/Makefile
index 042f79e..689eb33 100644
--- a/Makefile
+++ b/Makefile
@@ -209,7 +209,7 @@ BASIC_LDFLAGS =
 
 SCRIPT_SH = \
 	git-bisect.sh git-checkout.sh \
-	git-clean.sh git-clone.sh git-commit.sh \
+	git-clean.sh git-clone.sh \
 	git-ls-remote.sh \
 	git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
 	git-pull.sh git-rebase.sh git-rebase--interactive.sh \
@@ -256,7 +256,7 @@ EXTRA_PROGRAMS =
 BUILT_INS = \
 	git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
 	git-get-tar-commit-id$X git-init$X git-repo-config$X \
-	git-fsck-objects$X git-cherry-pick$X \
+	git-fsck-objects$X git-cherry-pick$X git-status$X\
 	$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
 
 # what 'all' will build and 'install' will install, in gitexecdir
@@ -326,6 +326,7 @@ BUILTIN_OBJS = \
 	builtin-check-attr.o \
 	builtin-checkout-index.o \
 	builtin-check-ref-format.o \
+	builtin-commit.o \
 	builtin-commit-tree.o \
 	builtin-count-objects.o \
 	builtin-describe.o \
@@ -364,7 +365,6 @@ BUILTIN_OBJS = \
 	builtin-rev-parse.o \
 	builtin-revert.o \
 	builtin-rm.o \
-	builtin-runstatus.o \
 	builtin-shortlog.o \
 	builtin-show-branch.o \
 	builtin-stripspace.o \
@@ -830,9 +830,6 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
 	chmod +x $@+ && \
 	mv $@+ $@
 
-git-status: git-commit
-	$(QUIET_GEN)cp $< $@+ && mv $@+ $@
-
 gitweb/gitweb.cgi: gitweb/gitweb.perl
 	$(QUIET_GEN)$(RM) $@ $@+ && \
 	sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
diff --git a/builtin-commit.c b/builtin-commit.c
new file mode 100644
index 0000000..56c7427
--- /dev/null
+++ b/builtin-commit.c
@@ -0,0 +1,608 @@
+/*
+ * Builtin "git commit"
+ *
+ * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>
+ * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "cache.h"
+#include "cache-tree.h"
+#include "builtin.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "commit.h"
+#include "revision.h"
+#include "wt-status.h"
+#include "run-command.h"
+#include "refs.h"
+#include "log-tree.h"
+#include "strbuf.h"
+#include "utf8.h"
+#include "parse-options.h"
+
+static const char * const builtin_commit_usage[] = {
+	"git-commit [options] [--] <filepattern>...",
+	NULL
+};
+
+static unsigned char head_sha1[20], merge_head_sha1[20];
+static char *use_message_buffer;
+static const char commit_editmsg[] = "COMMIT_EDITMSG";
+static struct lock_file lock_file;
+
+static char *logfile, *force_author, *message, *template_file;
+static char *edit_message, *use_message;
+static int all, edit_flag, also, interactive, only, amend, signoff;
+static int quiet, verbose, untracked_files, no_verify;
+
+static int no_edit, initial_commit, in_merge;
+const char *only_include_assumed;
+
+static struct option builtin_commit_options[] = {
+	OPT__QUIET(&quiet),
+	OPT__VERBOSE(&verbose),
+	OPT_GROUP("Commit message options"),
+
+	OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
+	OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
+	OPT_STRING('m', "message", &message, "MESSAGE", "specify commit message"),
+	OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
+	OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
+	OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by: header"),
+	OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
+	OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
+
+	OPT_GROUP("Commit contents options"),
+	OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
+	OPT_BOOLEAN('i', "include", &also, "add specified files to index for commit"),
+	OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"),
+	OPT_BOOLEAN('o', "only", &only, ""),
+	OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
+	OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
+	OPT_BOOLEAN(0, "untracked-files", &untracked_files, "show all untracked files"),
+
+	OPT_END()
+};
+
+static char *
+prepare_index(const char **files, const char *prefix)
+{
+	int fd;
+	struct tree *tree;
+	struct lock_file *next_index_lock;
+
+	fd = hold_locked_index(&lock_file, 1);
+	if (read_cache() < 0)
+		die("index file corrupt");
+
+	if (all) {
+		add_files_to_cache(verbose, NULL, files);
+		if (write_cache(fd, active_cache, active_nr) || close(fd))
+			die("unable to write new_index file");
+		return lock_file.filename;
+	} else if (also) {
+		add_files_to_cache(verbose, prefix, files);
+		if (write_cache(fd, active_cache, active_nr) || close(fd))
+			die("unable to write new_index file");
+		return lock_file.filename;
+	}
+
+	if (interactive)
+		interactive_add();
+
+	if (*files == NULL) {
+		/* Commit index as-is. */
+		rollback_lock_file(&lock_file);
+		return get_index_file();
+	}
+
+	/* update the user index file */
+	add_files_to_cache(verbose, prefix, files);
+	if (write_cache(fd, active_cache, active_nr) || close(fd))
+		die("unable to write new_index file");
+
+	if (!initial_commit) {
+		tree = parse_tree_indirect(head_sha1);
+		if (!tree)
+			die("failed to unpack HEAD tree object");
+		if (read_tree(tree, 0, NULL))
+			die("failed to read HEAD tree object");
+	}
+
+	/* Uh oh, abusing lock_file to create a garbage collected file */
+	next_index_lock = xmalloc(sizeof(*next_index_lock));
+	fd = hold_lock_file_for_update(next_index_lock,
+				       git_path("next-index-%d", getpid()), 1);
+	add_files_to_cache(verbose, prefix, files);
+	if (write_cache(fd, active_cache, active_nr) || close(fd))
+		die("unable to write new_index file");
+
+	return next_index_lock->filename;
+}
+
+static int run_status(FILE *fp, const char *index_file)
+{
+	struct wt_status s;
+
+	wt_status_prepare(&s);
+
+	if (amend) {
+		s.amend = 1;
+		s.reference = "HEAD^1";
+	}
+	s.verbose = verbose;
+	s.untracked = untracked_files;
+	s.index_file = index_file;
+	s.fp = fp;
+
+	wt_status_print(&s);
+
+	return s.commitable;
+}
+
+static const char sign_off_header[] = "Signed-off-by: ";
+
+static int prepare_log_message(const char *index_file)
+{
+	struct stat statbuf;
+	int commitable;
+	struct strbuf sb;
+	char *buffer;
+	FILE *fp;
+
+	strbuf_init(&sb, 0);
+	if (message) {
+		strbuf_add(&sb, message, strlen(message));
+	} else if (logfile && !strcmp(logfile, "-")) {
+		if (isatty(0))
+			fprintf(stderr, "(reading log message from standard input)\n");
+		if (strbuf_read(&sb, 0, 0) < 0)
+			die("could not read log from standard input");
+	} else if (logfile) {
+		if (strbuf_read_file(&sb, logfile, 0) < 0)
+			die("could not read log file '%s': %s",
+			    logfile, strerror(errno));
+	} else if (use_message) {
+		buffer = strstr(use_message_buffer, "\n\n");
+		if (!buffer || buffer[2] == '\0')
+			die("commit has empty message");
+		strbuf_add(&sb, buffer + 2, strlen(buffer + 2));
+	} else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
+		if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
+			die("could not read MERGE_MSG: %s", strerror(errno));
+	} else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
+		if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
+			die("could not read SQUASH_MSG: %s", strerror(errno));
+	} else if (!stat(template_file, &statbuf)) {
+		if (strbuf_read_file(&sb, template_file, 0) < 0)
+			die("could not read %s: %s",
+			    template_file, strerror(errno));
+	}
+
+	fp = fopen(git_path(commit_editmsg), "w");
+	if (fp == NULL)
+		die("could not open %s\n", git_path(commit_editmsg));
+		
+	stripspace(&sb, 0);
+	if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
+		die("could not write commit template: %s\n",
+		    strerror(errno));
+
+	if (signoff) {
+		const char *info, *bol;
+
+		info = git_committer_info(1);
+		strbuf_addch(&sb, '\0');
+		bol = strrchr(sb.buf + sb.len - 1, '\n');
+		if (!bol || prefixcmp(bol, sign_off_header))
+			fprintf(fp, "\n");
+		fprintf(fp, "%s%s\n", sign_off_header, git_committer_info(1));
+	}
+
+	strbuf_release(&sb);
+
+	if (in_merge && !no_edit) {
+		fprintf(fp,
+			"#\n"
+			"# It looks like you may be committing a MERGE.\n"
+			"# If this is not correct, please remove the file\n"
+			"#	%s\n"
+			"# and try again.\n"
+			"#\n",
+			git_path("MERGE_HEAD"));
+	}
+
+	fprintf(fp,
+		"\n"
+		"# Please enter the commit message for your changes.\n"
+		"# (Comment lines starting with '#' will not be included)\n");
+	if (only_include_assumed)
+		fprintf(fp, "# %s\n", only_include_assumed);
+
+	commitable = run_status(fp, index_file);
+
+	fclose(fp);
+
+	return commitable;
+}
+
+/* Find out if the message starting at position 'start' in the strbuf
+ * contains only whitespace and Signed-off-by lines. */
+static int message_is_empty(struct strbuf *sb, int start)
+{
+	struct strbuf tmpl;
+	const char *nl;
+	int eol, i;
+
+	/* See if the template is just a prefix of the message. */
+	strbuf_init(&tmpl, 0);
+	if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
+		stripspace(&tmpl, 1);
+		if (start + tmpl.len <= sb->len &&
+		    memcmp(tmpl.buf, sb->buf + start, tmpl.len) == 0)
+			start += tmpl.len;
+	}
+	strbuf_release(&tmpl);
+
+	/* Check if the rest is just whitespace and Signed-of-by's. */
+	for (i = start; i < sb->len; i++) {
+		nl = memchr(sb->buf + i, '\n', sb->len - i);
+		if (nl)
+			eol = nl - sb->buf;
+		else
+			eol = sb->len;
+
+		if (strlen(sign_off_header) <= eol - i &&
+		    !prefixcmp(sb->buf + i, sign_off_header)) {
+			i = eol;
+			continue;
+		}
+		while (i < eol)
+			if (!isspace(sb->buf[i++]))
+				return 0;
+	}
+
+	return 1;
+}
+
+static void determine_author_info(struct strbuf *sb)
+{
+	char *p, *eol;
+	char *name = NULL, *email = NULL;
+
+	if (use_message) {
+		p = strstr(use_message_buffer, "\nauthor");
+		if (!p)
+			die("invalid commit: %s\n", use_message);
+		p++;
+		eol = strchr(p, '\n');
+		if (!eol)
+			die("invalid commit: %s\n", use_message);
+
+		strbuf_add(sb, p, eol + 1 - p);
+	} else if (force_author) {
+		const char *eoname = strstr(force_author, " <");
+		const char *eomail = strchr(force_author, '>');
+
+		if (!eoname || !eomail)
+			die("malformed --author parameter\n");
+		name = xstrndup(force_author, eoname - force_author);
+		email = xstrndup(eoname + 2, eomail - eoname - 2);
+		strbuf_addf(sb, "author %s\n",
+			    fmt_ident(name, email, 
+				      getenv("GIT_AUTHOR_DATE"), 1));
+		free(name);
+		free(email);
+	} else {
+		strbuf_addf(sb, "author %s\n", git_author_info(1));
+	}
+}
+
+static int parse_and_validate_options(int argc, const char *argv[])
+{
+	int f = 0;
+
+	argc = parse_options(argc, argv, builtin_commit_options,
+			     builtin_commit_usage, 0);
+
+	if (logfile || message || use_message)
+		no_edit = 1;
+	if (edit_flag)
+		no_edit = 0;
+
+	if (get_sha1("HEAD", head_sha1))
+		initial_commit = 1;
+
+	if (!get_sha1("MERGE_HEAD", merge_head_sha1))
+		in_merge = 1;
+
+	/* Sanity check options */
+	if (amend && initial_commit)
+		die("You have nothing to amend.");
+	if (amend && in_merge)
+		die("You are in the middle of a merger -- cannot amend.");
+
+	if (use_message)
+		f++;
+	if (edit_message)
+		f++;
+	if (logfile)
+		f++;
+	if (f > 1)
+		die("Only one of -c/-C/-F can be used.");
+	if (message && f > 0)
+		die("Option -m cannot be combined with -c/-C/-F.");
+	if (edit_message)
+		use_message = edit_message;
+	if (amend)
+		use_message = "HEAD";
+	if (use_message) {
+		unsigned char sha1[20];
+		static char utf8[] = "UTF-8";
+		const char *out_enc;
+		char *enc, *end;
+		struct commit *commit;
+
+		if (get_sha1(use_message, sha1))
+			die("could not lookup commit %s", use_message);
+		commit = lookup_commit(sha1);
+		if (!commit || parse_commit(commit))
+			die("could not parse commit %s", use_message);
+
+		enc = strstr(commit->buffer, "\nencoding");
+		if (enc) {
+			end = strchr(enc + 10, '\n');
+			enc = xstrndup(enc + 10, end - (enc + 10));
+		} else {
+			enc = utf8;
+		}
+		out_enc = git_commit_encoding ? git_commit_encoding : utf8;
+
+		use_message_buffer =
+			reencode_string(commit->buffer, out_enc, enc);
+		if (enc != utf8)
+			free(enc);
+	}
+
+	if (also && only)
+		die("Only one of --include/--only can be used.");
+	if (!*argv && (also || (only && !amend)))
+		die("No paths with --include/--only does not make sense.");
+	if (!*argv && only && amend)
+		only_include_assumed = "Clever... amending the last one with dirty index.";
+	if (*argv && !also && !only) {
+		only_include_assumed = "Explicit paths specified without -i nor -o; assuming --only paths...";
+		also = 0;
+	}
+
+	if (all && interactive)
+		die("Cannot use -a, --interactive or -i at the same time.");
+	else if (all && argc > 0)
+		die("Paths with -a does not make sense.");
+	else if (interactive && **argv)
+		die("Paths with --interactive does not make sense.");
+
+	return argc;
+}
+
+int cmd_status(int argc, const char **argv, const char *prefix)
+{
+	const char *index_file;
+	int commitable;
+
+	git_config(git_status_config);
+
+	argc = parse_and_validate_options(argc, argv);
+
+	index_file = prepare_index(argv, prefix);
+
+	commitable = run_status(stdout, index_file);
+
+	rollback_lock_file(&lock_file);
+
+	return commitable ? 0 : 1;
+}
+
+static int run_hook(const char *index_file, const char *name, const char *arg)
+{
+	struct child_process hook;
+	const char *argv[3], *env[2];
+	char index[PATH_MAX];
+
+	argv[0] = git_path("hooks/%s", name);
+	argv[1] = arg;
+	argv[2] = NULL;
+	snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
+	env[0] = index;
+	env[1] = NULL;
+
+	if (access(argv[0], X_OK) < 0)
+		return 0;
+
+	memset(&hook, 0, sizeof(hook));
+	hook.argv = argv;
+	hook.no_stdin = 1;
+	hook.stdout_to_stderr = 1;
+	hook.env = env;
+
+	return run_command(&hook);
+}
+
+static void print_summary(const char *prefix, const unsigned char *sha1)
+{
+	struct rev_info rev;
+	struct commit *commit;
+
+	commit = lookup_commit(sha1);
+	if (!commit)
+		die("couldn't look up newly created commit\n");
+	if (!commit || parse_commit(commit))
+		die("could not parse newly created commit");
+
+	init_revisions(&rev, prefix);
+	setup_revisions(0, NULL, &rev, NULL);
+
+	rev.abbrev = 0;
+	rev.diff = 1;
+	rev.diffopt.output_format =
+		DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
+
+	rev.verbose_header = 1;
+	rev.show_root_diff = 1;
+	rev.commit_format = get_commit_format("format:%h: %s");
+	rev.always_show_header = 1;
+		
+	printf("Created %scommit ", initial_commit ? "initial " : "");
+
+	log_tree_commit(&rev, commit);
+}
+
+int git_commit_config(const char *k, const char *v)
+{
+	if (!strcmp(k, "commit.template")) {
+		template_file = xstrdup(v);
+		return 0;
+	}
+
+	return git_status_config(k, v);
+}
+
+static const char commit_utf8_warn[] =
+"Warning: commit message does not conform to UTF-8.\n"
+"You may want to amend it after fixing the message, or set the config\n"
+"variable i18n.commitencoding to the encoding your project uses.\n";
+
+int cmd_commit(int argc, const char **argv, const char *prefix)
+{
+	int header_len, parent_count = 0;
+	struct strbuf sb;
+	const char *index_file, *reflog_msg;
+	char *nl, *header_line;
+	unsigned char commit_sha1[20];
+	struct ref_lock *ref_lock;
+
+	git_config(git_commit_config);
+
+	argc = parse_and_validate_options(argc, argv);
+
+	index_file = prepare_index(argv, prefix);
+
+	if (!no_verify && run_hook(index_file, "pre-commit", NULL))
+		exit(1);
+
+	if (!prepare_log_message(index_file) && !in_merge) {
+		run_status(stdout, index_file);
+		unlink(commit_editmsg);
+		return 1;
+	}
+
+	strbuf_init(&sb, 0);
+
+	/* Start building up the commit header */
+	read_cache_from(index_file);
+	active_cache_tree = cache_tree();
+	if (cache_tree_update(active_cache_tree,
+			      active_cache, active_nr, 0, 0) < 0)
+		die("Error building trees");
+	strbuf_addf(&sb, "tree %s\n",
+		    sha1_to_hex(active_cache_tree->sha1));
+
+	/* Determine parents */
+	if (initial_commit) {
+		reflog_msg = "commit (initial)"; 
+		parent_count = 0;
+	} else if (amend) {
+		struct commit_list *c;
+		struct commit *commit;
+
+		reflog_msg = "commit (amend)";
+		commit = lookup_commit(head_sha1);
+		if (!commit || parse_commit(commit))
+			die("could not parse HEAD commit");
+
+		for (c = commit->parents; c; c = c->next)
+			strbuf_addf(&sb, "parent %s\n",
+				      sha1_to_hex(c->item->object.sha1));
+	} else if (in_merge) {
+		struct strbuf m;
+		FILE *fp;
+
+		reflog_msg = "commit (merge)";
+		strbuf_addf(&sb, "parent %s\n", sha1_to_hex(head_sha1));
+		strbuf_init(&m, 0);
+		fp = fopen(git_path("MERGE_HEAD"), "r");
+		if (fp == NULL)
+			die("could not open %s for reading: %s",
+			    git_path("MERGE_HEAD"), strerror(errno));
+		while (strbuf_getline(&m, fp, '\n') != EOF)
+			strbuf_addf(&sb, "parent %s\n", m.buf);
+		fclose(fp);
+		strbuf_release(&m);
+	} else {
+		reflog_msg = "commit";
+		strbuf_addf(&sb, "parent %s\n", sha1_to_hex(head_sha1));
+	}
+
+	determine_author_info(&sb);
+	strbuf_addf(&sb, "committer %s\n", git_committer_info(1));
+	if (!is_encoding_utf8(git_commit_encoding))
+		strbuf_addf(&sb, "encoding %s\n", git_commit_encoding);
+	strbuf_addch(&sb, '\n');
+
+	/* Get the commit message and validate it */
+	header_len = sb.len;
+	if (!no_edit) {
+		fprintf(stderr, "launching editor, log %s\n", logfile);
+		launch_editor(git_path(commit_editmsg), &sb);
+	}
+	else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0)
+		die("could not read commit message\n");
+	if (run_hook(index_file, "commit-msg", commit_editmsg))
+		exit(1);
+	stripspace(&sb, 1);
+	if (sb.len < header_len ||
+	    message_is_empty(&sb, header_len))
+		die("* no commit message?  aborting commit.");
+	strbuf_addch(&sb, '\0');
+	if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))
+		fprintf(stderr, commit_utf8_warn);
+
+	if (write_sha1_file(sb.buf, sb.len - 1, commit_type, commit_sha1))
+		die("failed to write commit object");
+		       
+	ref_lock = lock_any_ref_for_update("HEAD",
+					   initial_commit ? NULL : head_sha1,
+					   0);
+
+	nl = strchr(sb.buf + header_len, '\n');
+	header_line = xstrndup(sb.buf + header_len,
+			       nl - (sb.buf + header_len));
+	strbuf_release(&sb);
+	strbuf_addf(&sb, "%s: %s\n", reflog_msg, header_line);
+	strbuf_addch(&sb, '\0');
+	free(header_line);
+
+	if (!ref_lock)
+		die("cannot lock HEAD ref");
+	if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0)
+		die("cannot update HEAD ref");
+
+	unlink(git_path("MERGE_HEAD"));
+	unlink(git_path("MERGE_MSG"));
+
+	if (lock_file.filename[0] && commit_locked_index(&lock_file))
+		die("failed to write new index");
+
+	rerere();
+
+	run_hook(index_file, "post-commit", NULL);
+
+	if (!quiet)
+		print_summary(prefix, commit_sha1);
+
+	return 0;
+}
diff --git a/builtin-tag.c b/builtin-tag.c
index 66e5a58..e6bae69 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -17,7 +17,7 @@ static const char builtin_tag_usage[] =
 
 static char signingkey[1000];
 
-static void launch_editor(const char *path, struct strbuf *buffer)
+void launch_editor(const char *path, struct strbuf *buffer)
 {
 	const char *editor, *terminal;
 	struct child_process child;
diff --git a/builtin.h b/builtin.h
index 9a6213a..0f8456c 100644
--- a/builtin.h
+++ b/builtin.h
@@ -24,6 +24,7 @@ extern int cmd_check_attr(int argc, const char **argv, const char *prefix);
 extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
 extern int cmd_cherry(int argc, const char **argv, const char *prefix);
 extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
+extern int cmd_commit(int argc, const char **argv, const char *prefix);
 extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
 extern int cmd_describe(int argc, const char **argv, const char *prefix);
@@ -68,10 +69,10 @@ extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
 extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
 extern int cmd_revert(int argc, const char **argv, const char *prefix);
 extern int cmd_rm(int argc, const char **argv, const char *prefix);
-extern int cmd_runstatus(int argc, const char **argv, const char *prefix);
 extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
 extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
+extern int cmd_status(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
 extern int cmd_tag(int argc, const char **argv, const char *prefix);
diff --git a/contrib/examples/git-commit.sh b/contrib/examples/git-commit.sh
new file mode 100755
index 0000000..fcb8443
--- /dev/null
+++ b/contrib/examples/git-commit.sh
@@ -0,0 +1,628 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+# Copyright (c) 2006 Junio C Hamano
+
+USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]'
+SUBDIRECTORY_OK=Yes
+. git-sh-setup
+require_work_tree
+
+git rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
+
+case "$0" in
+*status)
+	status_only=t
+	;;
+*commit)
+	status_only=
+	;;
+esac
+
+refuse_partial () {
+	echo >&2 "$1"
+	echo >&2 "You might have meant to say 'git commit -i paths...', perhaps?"
+	exit 1
+}
+
+TMP_INDEX=
+THIS_INDEX="$GIT_DIR/index"
+NEXT_INDEX="$GIT_DIR/next-index$$"
+rm -f "$NEXT_INDEX"
+save_index () {
+	cp -p "$THIS_INDEX" "$NEXT_INDEX"
+}
+
+run_status () {
+	# If TMP_INDEX is defined, that means we are doing
+	# "--only" partial commit, and that index file is used
+	# to build the tree for the commit.  Otherwise, if
+	# NEXT_INDEX exists, that is the index file used to
+	# make the commit.  Otherwise we are using as-is commit
+	# so the regular index file is what we use to compare.
+	if test '' != "$TMP_INDEX"
+	then
+		GIT_INDEX_FILE="$TMP_INDEX"
+		export GIT_INDEX_FILE
+	elif test -f "$NEXT_INDEX"
+	then
+		GIT_INDEX_FILE="$NEXT_INDEX"
+		export GIT_INDEX_FILE
+	fi
+
+	if test "$status_only" = "t" -o "$use_status_color" = "t"; then
+		color=
+	else
+		color=--nocolor
+	fi
+	git runstatus ${color} \
+		${verbose:+--verbose} \
+		${amend:+--amend} \
+		${untracked_files:+--untracked}
+}
+
+trap '
+	test -z "$TMP_INDEX" || {
+		test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
+	}
+	rm -f "$NEXT_INDEX"
+' 0
+
+################################################################
+# Command line argument parsing and sanity checking
+
+all=
+also=
+interactive=
+only=
+logfile=
+use_commit=
+amend=
+edit_flag=
+no_edit=
+log_given=
+log_message=
+verify=t
+quiet=
+verbose=
+signoff=
+force_author=
+only_include_assumed=
+untracked_files=
+templatefile="`git config commit.template`"
+while test $# != 0
+do
+	case "$1" in
+	-F|--F|-f|--f|--fi|--fil|--file)
+		case "$#" in 1) usage ;; esac
+		shift
+		no_edit=t
+		log_given=t$log_given
+		logfile="$1"
+		;;
+	-F*|-f*)
+		no_edit=t
+		log_given=t$log_given
+		logfile="${1#-[Ff]}"
+		;;
+	--F=*|--f=*|--fi=*|--fil=*|--file=*)
+		no_edit=t
+		log_given=t$log_given
+		logfile="${1#*=}"
+		;;
+	-a|--a|--al|--all)
+		all=t
+		;;
+	--au=*|--aut=*|--auth=*|--autho=*|--author=*)
+		force_author="${1#*=}"
+		;;
+	--au|--aut|--auth|--autho|--author)
+		case "$#" in 1) usage ;; esac
+		shift
+		force_author="$1"
+		;;
+	-e|--e|--ed|--edi|--edit)
+		edit_flag=t
+		;;
+	-i|--i|--in|--inc|--incl|--inclu|--includ|--include)
+		also=t
+		;;
+	--int|--inte|--inter|--intera|--interac|--interact|--interacti|\
+	--interactiv|--interactive)
+		interactive=t
+		;;
+	-o|--o|--on|--onl|--only)
+		only=t
+		;;
+	-m|--m|--me|--mes|--mess|--messa|--messag|--message)
+		case "$#" in 1) usage ;; esac
+		shift
+		log_given=m$log_given
+		log_message="${log_message:+${log_message}
+
+}$1"
+		no_edit=t
+		;;
+	-m*)
+		log_given=m$log_given
+		log_message="${log_message:+${log_message}
+
+}${1#-m}"
+		no_edit=t
+		;;
+	--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
+		log_given=m$log_given
+		log_message="${log_message:+${log_message}
+
+}${1#*=}"
+		no_edit=t
+		;;
+	-n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\
+	--no-verify)
+		verify=
+		;;
+	--a|--am|--ame|--amen|--amend)
+		amend=t
+		use_commit=HEAD
+		;;
+	-c)
+		case "$#" in 1) usage ;; esac
+		shift
+		log_given=t$log_given
+		use_commit="$1"
+		no_edit=
+		;;
+	--ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\
+	--reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\
+	--reedit-messag=*|--reedit-message=*)
+		log_given=t$log_given
+		use_commit="${1#*=}"
+		no_edit=
+		;;
+	--ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\
+	--reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\
+	--reedit-message)
+		case "$#" in 1) usage ;; esac
+		shift
+		log_given=t$log_given
+		use_commit="$1"
+		no_edit=
+		;;
+	-C)
+		case "$#" in 1) usage ;; esac
+		shift
+		log_given=t$log_given
+		use_commit="$1"
+		no_edit=t
+		;;
+	--reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\
+	--reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\
+	--reuse-message=*)
+		log_given=t$log_given
+		use_commit="${1#*=}"
+		no_edit=t
+		;;
+	--reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\
+	--reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)
+		case "$#" in 1) usage ;; esac
+		shift
+		log_given=t$log_given
+		use_commit="$1"
+		no_edit=t
+		;;
+	-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
+		signoff=t
+		;;
+	-t|--t|--te|--tem|--temp|--templ|--templa|--templat|--template)
+		case "$#" in 1) usage ;; esac
+		shift
+		templatefile="$1"
+		no_edit=
+		;;
+	-q|--q|--qu|--qui|--quie|--quiet)
+		quiet=t
+		;;
+	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
+		verbose=t
+		;;
+	-u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\
+	--untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\
+	--untracked-file|--untracked-files)
+		untracked_files=t
+		;;
+	--)
+		shift
+		break
+		;;
+	-*)
+		usage
+		;;
+	*)
+		break
+		;;
+	esac
+	shift
+done
+case "$edit_flag" in t) no_edit= ;; esac
+
+################################################################
+# Sanity check options
+
+case "$amend,$initial_commit" in
+t,t)
+	die "You do not have anything to amend." ;;
+t,)
+	if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
+		die "You are in the middle of a merge -- cannot amend."
+	fi ;;
+esac
+
+case "$log_given" in
+tt*)
+	die "Only one of -c/-C/-F can be used." ;;
+*tm*|*mt*)
+	die "Option -m cannot be combined with -c/-C/-F." ;;
+esac
+
+case "$#,$also,$only,$amend" in
+*,t,t,*)
+	die "Only one of --include/--only can be used." ;;
+0,t,,* | 0,,t,)
+	die "No paths with --include/--only does not make sense." ;;
+0,,t,t)
+	only_include_assumed="# Clever... amending the last one with dirty index." ;;
+0,,,*)
+	;;
+*,,,*)
+	only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..."
+	also=
+	;;
+esac
+unset only
+case "$all,$interactive,$also,$#" in
+*t,*t,*)
+	die "Cannot use -a, --interactive or -i at the same time." ;;
+t,,[1-9]*)
+	die "Paths with -a does not make sense." ;;
+,t,[1-9]*)
+	die "Paths with --interactive does not make sense." ;;
+,,t,0)
+	die "No paths with -i does not make sense." ;;
+esac
+
+if test ! -z "$templatefile" -a -z "$log_given"
+then
+	if test ! -f "$templatefile"
+	then
+		die "Commit template file does not exist."
+	fi
+fi
+
+################################################################
+# Prepare index to have a tree to be committed
+
+case "$all,$also" in
+t,)
+	if test ! -f "$THIS_INDEX"
+	then
+		die 'nothing to commit (use "git add file1 file2" to include for commit)'
+	fi
+	save_index &&
+	(
+		cd_to_toplevel &&
+		GIT_INDEX_FILE="$NEXT_INDEX" &&
+		export GIT_INDEX_FILE &&
+		git diff-files --name-only -z |
+		git update-index --remove -z --stdin
+	) || exit
+	;;
+,t)
+	save_index &&
+	git ls-files --error-unmatch -- "$@" >/dev/null || exit
+
+	git diff-files --name-only -z -- "$@"  |
+	(
+		cd_to_toplevel &&
+		GIT_INDEX_FILE="$NEXT_INDEX" &&
+		export GIT_INDEX_FILE &&
+		git update-index --remove -z --stdin
+	) || exit
+	;;
+,)
+	if test "$interactive" = t; then
+		git add --interactive || exit
+	fi
+	case "$#" in
+	0)
+		;; # commit as-is
+	*)
+		if test -f "$GIT_DIR/MERGE_HEAD"
+		then
+			refuse_partial "Cannot do a partial commit during a merge."
+		fi
+
+		TMP_INDEX="$GIT_DIR/tmp-index$$"
+		W=
+		test -z "$initial_commit" && W=--with-tree=HEAD
+		commit_only=`git ls-files --error-unmatch $W -- "$@"` || exit
+
+		# Build a temporary index and update the real index
+		# the same way.
+		if test -z "$initial_commit"
+		then
+			GIT_INDEX_FILE="$THIS_INDEX" \
+			git read-tree --index-output="$TMP_INDEX" -i -m HEAD
+		else
+			rm -f "$TMP_INDEX"
+		fi || exit
+
+		printf '%s\n' "$commit_only" |
+		GIT_INDEX_FILE="$TMP_INDEX" \
+		git update-index --add --remove --stdin &&
+
+		save_index &&
+		printf '%s\n' "$commit_only" |
+		(
+			GIT_INDEX_FILE="$NEXT_INDEX"
+			export GIT_INDEX_FILE
+			git update-index --add --remove --stdin
+		) || exit
+		;;
+	esac
+	;;
+esac
+
+################################################################
+# If we do as-is commit, the index file will be THIS_INDEX,
+# otherwise NEXT_INDEX after we make this commit.  We leave
+# the index as is if we abort.
+
+if test -f "$NEXT_INDEX"
+then
+	USE_INDEX="$NEXT_INDEX"
+else
+	USE_INDEX="$THIS_INDEX"
+fi
+
+case "$status_only" in
+t)
+	# This will silently fail in a read-only repository, which is
+	# what we want.
+	GIT_INDEX_FILE="$USE_INDEX" git update-index -q --unmerged --refresh
+	run_status
+	exit $?
+	;;
+'')
+	GIT_INDEX_FILE="$USE_INDEX" git update-index -q --refresh || exit
+	;;
+esac
+
+################################################################
+# Grab commit message, write out tree and make commit.
+
+if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit
+then
+    GIT_INDEX_FILE="${TMP_INDEX:-${USE_INDEX}}" "$GIT_DIR"/hooks/pre-commit \
+    || exit
+fi
+
+if test "$log_message" != ''
+then
+	printf '%s\n' "$log_message"
+elif test "$logfile" != ""
+then
+	if test "$logfile" = -
+	then
+		test -t 0 &&
+		echo >&2 "(reading log message from standard input)"
+		cat
+	else
+		cat <"$logfile"
+	fi
+elif test "$use_commit" != ""
+then
+	encoding=$(git config i18n.commitencoding || echo UTF-8)
+	git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
+	sed -e '1,/^$/d' -e 's/^    //'
+elif test -f "$GIT_DIR/MERGE_MSG"
+then
+	cat "$GIT_DIR/MERGE_MSG"
+elif test -f "$GIT_DIR/SQUASH_MSG"
+then
+	cat "$GIT_DIR/SQUASH_MSG"
+elif test "$templatefile" != ""
+then
+	cat "$templatefile"
+fi | git stripspace >"$GIT_DIR"/COMMIT_EDITMSG
+
+case "$signoff" in
+t)
+	sign=$(git-var GIT_COMMITTER_IDENT | sed -e '
+		s/>.*/>/
+		s/^/Signed-off-by: /
+		')
+	blank_before_signoff=
+	tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
+	grep 'Signed-off-by:' >/dev/null || blank_before_signoff='
+'
+	tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
+	grep "$sign"$ >/dev/null ||
+	printf '%s%s\n' "$blank_before_signoff" "$sign" \
+		>>"$GIT_DIR"/COMMIT_EDITMSG
+	;;
+esac
+
+if test -f "$GIT_DIR/MERGE_HEAD" && test -z "$no_edit"; then
+	echo "#"
+	echo "# It looks like you may be committing a MERGE."
+	echo "# If this is not correct, please remove the file"
+	printf '%s\n' "#	$GIT_DIR/MERGE_HEAD"
+	echo "# and try again"
+	echo "#"
+fi >>"$GIT_DIR"/COMMIT_EDITMSG
+
+# Author
+if test '' != "$use_commit"
+then
+	eval "$(get_author_ident_from_commit "$use_commit")"
+	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
+fi
+if test '' != "$force_author"
+then
+	GIT_AUTHOR_NAME=`expr "z$force_author" : 'z\(.*[^ ]\) *<.*'` &&
+	GIT_AUTHOR_EMAIL=`expr "z$force_author" : '.*\(<.*\)'` &&
+	test '' != "$GIT_AUTHOR_NAME" &&
+	test '' != "$GIT_AUTHOR_EMAIL" ||
+	die "malformed --author parameter"
+	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
+fi
+
+PARENTS="-p HEAD"
+if test -z "$initial_commit"
+then
+	rloga='commit'
+	if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
+		rloga='commit (merge)'
+		PARENTS="-p HEAD "`sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD"`
+	elif test -n "$amend"; then
+		rloga='commit (amend)'
+		PARENTS=$(git cat-file commit HEAD |
+			sed -n -e '/^$/q' -e 's/^parent /-p /p')
+	fi
+	current="$(git rev-parse --verify HEAD)"
+else
+	if [ -z "$(git ls-files)" ]; then
+		echo >&2 'nothing to commit (use "git add file1 file2" to include for commit)'
+		exit 1
+	fi
+	PARENTS=""
+	rloga='commit (initial)'
+	current=''
+fi
+set_reflog_action "$rloga"
+
+if test -z "$no_edit"
+then
+	{
+		echo ""
+		echo "# Please enter the commit message for your changes."
+		echo "# (Comment lines starting with '#' will not be included)"
+		test -z "$only_include_assumed" || echo "$only_include_assumed"
+		run_status
+	} >>"$GIT_DIR"/COMMIT_EDITMSG
+else
+	# we need to check if there is anything to commit
+	run_status >/dev/null
+fi
+if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ]
+then
+	rm -f "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
+	use_status_color=t
+	run_status
+	exit 1
+fi
+
+case "$no_edit" in
+'')
+	git-var GIT_AUTHOR_IDENT > /dev/null  || die
+	git-var GIT_COMMITTER_IDENT > /dev/null  || die
+	git_editor "$GIT_DIR/COMMIT_EDITMSG"
+	;;
+esac
+
+case "$verify" in
+t)
+	if test -x "$GIT_DIR"/hooks/commit-msg
+	then
+		"$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG || exit
+	fi
+esac
+
+if test -z "$no_edit"
+then
+    sed -e '
+        /^diff --git a\/.*/{
+	    s///
+	    q
+	}
+	/^#/d
+    ' "$GIT_DIR"/COMMIT_EDITMSG
+else
+    cat "$GIT_DIR"/COMMIT_EDITMSG
+fi |
+git stripspace >"$GIT_DIR"/COMMIT_MSG
+
+# Test whether the commit message has any content we didn't supply.
+have_commitmsg=
+grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
+	git stripspace > "$GIT_DIR"/COMMIT_BAREMSG
+
+# Is the commit message totally empty?
+if test -s "$GIT_DIR"/COMMIT_BAREMSG
+then
+	if test "$templatefile" != ""
+	then
+		# Test whether this is just the unaltered template.
+		if cnt=`sed -e '/^#/d' < "$templatefile" |
+			git stripspace |
+			diff "$GIT_DIR"/COMMIT_BAREMSG - |
+			wc -l` &&
+		   test 0 -lt $cnt
+		then
+			have_commitmsg=t
+		fi
+	else
+		# No template, so the content in the commit message must
+		# have come from the user.
+		have_commitmsg=t
+	fi
+fi
+
+rm -f "$GIT_DIR"/COMMIT_BAREMSG
+
+if test "$have_commitmsg" = "t"
+then
+	if test -z "$TMP_INDEX"
+	then
+		tree=$(GIT_INDEX_FILE="$USE_INDEX" git write-tree)
+	else
+		tree=$(GIT_INDEX_FILE="$TMP_INDEX" git write-tree) &&
+		rm -f "$TMP_INDEX"
+	fi &&
+	commit=$(git commit-tree $tree $PARENTS <"$GIT_DIR/COMMIT_MSG") &&
+	rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
+	git update-ref -m "$GIT_REFLOG_ACTION: $rlogm" HEAD $commit "$current" &&
+	rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" &&
+	if test -f "$NEXT_INDEX"
+	then
+		mv "$NEXT_INDEX" "$THIS_INDEX"
+	else
+		: ;# happy
+	fi
+else
+	echo >&2 "* no commit message?  aborting commit."
+	false
+fi
+ret="$?"
+rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
+
+cd_to_toplevel
+
+git rerere
+
+if test "$ret" = 0
+then
+	git gc --auto
+	if test -x "$GIT_DIR"/hooks/post-commit
+	then
+		"$GIT_DIR"/hooks/post-commit
+	fi
+	if test -z "$quiet"
+	then
+		commit=`git diff-tree --always --shortstat --pretty="format:%h: %s"\
+		       --summary --root HEAD --`
+		echo "Created${initial_commit:+ initial} commit $commit"
+	fi
+fi
+
+exit "$ret"
diff --git a/git-commit.sh b/git-commit.sh
deleted file mode 100755
index fcb8443..0000000
--- a/git-commit.sh
+++ /dev/null
@@ -1,628 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-# Copyright (c) 2006 Junio C Hamano
-
-USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]'
-SUBDIRECTORY_OK=Yes
-. git-sh-setup
-require_work_tree
-
-git rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
-
-case "$0" in
-*status)
-	status_only=t
-	;;
-*commit)
-	status_only=
-	;;
-esac
-
-refuse_partial () {
-	echo >&2 "$1"
-	echo >&2 "You might have meant to say 'git commit -i paths...', perhaps?"
-	exit 1
-}
-
-TMP_INDEX=
-THIS_INDEX="$GIT_DIR/index"
-NEXT_INDEX="$GIT_DIR/next-index$$"
-rm -f "$NEXT_INDEX"
-save_index () {
-	cp -p "$THIS_INDEX" "$NEXT_INDEX"
-}
-
-run_status () {
-	# If TMP_INDEX is defined, that means we are doing
-	# "--only" partial commit, and that index file is used
-	# to build the tree for the commit.  Otherwise, if
-	# NEXT_INDEX exists, that is the index file used to
-	# make the commit.  Otherwise we are using as-is commit
-	# so the regular index file is what we use to compare.
-	if test '' != "$TMP_INDEX"
-	then
-		GIT_INDEX_FILE="$TMP_INDEX"
-		export GIT_INDEX_FILE
-	elif test -f "$NEXT_INDEX"
-	then
-		GIT_INDEX_FILE="$NEXT_INDEX"
-		export GIT_INDEX_FILE
-	fi
-
-	if test "$status_only" = "t" -o "$use_status_color" = "t"; then
-		color=
-	else
-		color=--nocolor
-	fi
-	git runstatus ${color} \
-		${verbose:+--verbose} \
-		${amend:+--amend} \
-		${untracked_files:+--untracked}
-}
-
-trap '
-	test -z "$TMP_INDEX" || {
-		test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
-	}
-	rm -f "$NEXT_INDEX"
-' 0
-
-################################################################
-# Command line argument parsing and sanity checking
-
-all=
-also=
-interactive=
-only=
-logfile=
-use_commit=
-amend=
-edit_flag=
-no_edit=
-log_given=
-log_message=
-verify=t
-quiet=
-verbose=
-signoff=
-force_author=
-only_include_assumed=
-untracked_files=
-templatefile="`git config commit.template`"
-while test $# != 0
-do
-	case "$1" in
-	-F|--F|-f|--f|--fi|--fil|--file)
-		case "$#" in 1) usage ;; esac
-		shift
-		no_edit=t
-		log_given=t$log_given
-		logfile="$1"
-		;;
-	-F*|-f*)
-		no_edit=t
-		log_given=t$log_given
-		logfile="${1#-[Ff]}"
-		;;
-	--F=*|--f=*|--fi=*|--fil=*|--file=*)
-		no_edit=t
-		log_given=t$log_given
-		logfile="${1#*=}"
-		;;
-	-a|--a|--al|--all)
-		all=t
-		;;
-	--au=*|--aut=*|--auth=*|--autho=*|--author=*)
-		force_author="${1#*=}"
-		;;
-	--au|--aut|--auth|--autho|--author)
-		case "$#" in 1) usage ;; esac
-		shift
-		force_author="$1"
-		;;
-	-e|--e|--ed|--edi|--edit)
-		edit_flag=t
-		;;
-	-i|--i|--in|--inc|--incl|--inclu|--includ|--include)
-		also=t
-		;;
-	--int|--inte|--inter|--intera|--interac|--interact|--interacti|\
-	--interactiv|--interactive)
-		interactive=t
-		;;
-	-o|--o|--on|--onl|--only)
-		only=t
-		;;
-	-m|--m|--me|--mes|--mess|--messa|--messag|--message)
-		case "$#" in 1) usage ;; esac
-		shift
-		log_given=m$log_given
-		log_message="${log_message:+${log_message}
-
-}$1"
-		no_edit=t
-		;;
-	-m*)
-		log_given=m$log_given
-		log_message="${log_message:+${log_message}
-
-}${1#-m}"
-		no_edit=t
-		;;
-	--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
-		log_given=m$log_given
-		log_message="${log_message:+${log_message}
-
-}${1#*=}"
-		no_edit=t
-		;;
-	-n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\
-	--no-verify)
-		verify=
-		;;
-	--a|--am|--ame|--amen|--amend)
-		amend=t
-		use_commit=HEAD
-		;;
-	-c)
-		case "$#" in 1) usage ;; esac
-		shift
-		log_given=t$log_given
-		use_commit="$1"
-		no_edit=
-		;;
-	--ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\
-	--reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\
-	--reedit-messag=*|--reedit-message=*)
-		log_given=t$log_given
-		use_commit="${1#*=}"
-		no_edit=
-		;;
-	--ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\
-	--reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\
-	--reedit-message)
-		case "$#" in 1) usage ;; esac
-		shift
-		log_given=t$log_given
-		use_commit="$1"
-		no_edit=
-		;;
-	-C)
-		case "$#" in 1) usage ;; esac
-		shift
-		log_given=t$log_given
-		use_commit="$1"
-		no_edit=t
-		;;
-	--reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\
-	--reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\
-	--reuse-message=*)
-		log_given=t$log_given
-		use_commit="${1#*=}"
-		no_edit=t
-		;;
-	--reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\
-	--reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)
-		case "$#" in 1) usage ;; esac
-		shift
-		log_given=t$log_given
-		use_commit="$1"
-		no_edit=t
-		;;
-	-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
-		signoff=t
-		;;
-	-t|--t|--te|--tem|--temp|--templ|--templa|--templat|--template)
-		case "$#" in 1) usage ;; esac
-		shift
-		templatefile="$1"
-		no_edit=
-		;;
-	-q|--q|--qu|--qui|--quie|--quiet)
-		quiet=t
-		;;
-	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
-		verbose=t
-		;;
-	-u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\
-	--untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\
-	--untracked-file|--untracked-files)
-		untracked_files=t
-		;;
-	--)
-		shift
-		break
-		;;
-	-*)
-		usage
-		;;
-	*)
-		break
-		;;
-	esac
-	shift
-done
-case "$edit_flag" in t) no_edit= ;; esac
-
-################################################################
-# Sanity check options
-
-case "$amend,$initial_commit" in
-t,t)
-	die "You do not have anything to amend." ;;
-t,)
-	if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
-		die "You are in the middle of a merge -- cannot amend."
-	fi ;;
-esac
-
-case "$log_given" in
-tt*)
-	die "Only one of -c/-C/-F can be used." ;;
-*tm*|*mt*)
-	die "Option -m cannot be combined with -c/-C/-F." ;;
-esac
-
-case "$#,$also,$only,$amend" in
-*,t,t,*)
-	die "Only one of --include/--only can be used." ;;
-0,t,,* | 0,,t,)
-	die "No paths with --include/--only does not make sense." ;;
-0,,t,t)
-	only_include_assumed="# Clever... amending the last one with dirty index." ;;
-0,,,*)
-	;;
-*,,,*)
-	only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..."
-	also=
-	;;
-esac
-unset only
-case "$all,$interactive,$also,$#" in
-*t,*t,*)
-	die "Cannot use -a, --interactive or -i at the same time." ;;
-t,,[1-9]*)
-	die "Paths with -a does not make sense." ;;
-,t,[1-9]*)
-	die "Paths with --interactive does not make sense." ;;
-,,t,0)
-	die "No paths with -i does not make sense." ;;
-esac
-
-if test ! -z "$templatefile" -a -z "$log_given"
-then
-	if test ! -f "$templatefile"
-	then
-		die "Commit template file does not exist."
-	fi
-fi
-
-################################################################
-# Prepare index to have a tree to be committed
-
-case "$all,$also" in
-t,)
-	if test ! -f "$THIS_INDEX"
-	then
-		die 'nothing to commit (use "git add file1 file2" to include for commit)'
-	fi
-	save_index &&
-	(
-		cd_to_toplevel &&
-		GIT_INDEX_FILE="$NEXT_INDEX" &&
-		export GIT_INDEX_FILE &&
-		git diff-files --name-only -z |
-		git update-index --remove -z --stdin
-	) || exit
-	;;
-,t)
-	save_index &&
-	git ls-files --error-unmatch -- "$@" >/dev/null || exit
-
-	git diff-files --name-only -z -- "$@"  |
-	(
-		cd_to_toplevel &&
-		GIT_INDEX_FILE="$NEXT_INDEX" &&
-		export GIT_INDEX_FILE &&
-		git update-index --remove -z --stdin
-	) || exit
-	;;
-,)
-	if test "$interactive" = t; then
-		git add --interactive || exit
-	fi
-	case "$#" in
-	0)
-		;; # commit as-is
-	*)
-		if test -f "$GIT_DIR/MERGE_HEAD"
-		then
-			refuse_partial "Cannot do a partial commit during a merge."
-		fi
-
-		TMP_INDEX="$GIT_DIR/tmp-index$$"
-		W=
-		test -z "$initial_commit" && W=--with-tree=HEAD
-		commit_only=`git ls-files --error-unmatch $W -- "$@"` || exit
-
-		# Build a temporary index and update the real index
-		# the same way.
-		if test -z "$initial_commit"
-		then
-			GIT_INDEX_FILE="$THIS_INDEX" \
-			git read-tree --index-output="$TMP_INDEX" -i -m HEAD
-		else
-			rm -f "$TMP_INDEX"
-		fi || exit
-
-		printf '%s\n' "$commit_only" |
-		GIT_INDEX_FILE="$TMP_INDEX" \
-		git update-index --add --remove --stdin &&
-
-		save_index &&
-		printf '%s\n' "$commit_only" |
-		(
-			GIT_INDEX_FILE="$NEXT_INDEX"
-			export GIT_INDEX_FILE
-			git update-index --add --remove --stdin
-		) || exit
-		;;
-	esac
-	;;
-esac
-
-################################################################
-# If we do as-is commit, the index file will be THIS_INDEX,
-# otherwise NEXT_INDEX after we make this commit.  We leave
-# the index as is if we abort.
-
-if test -f "$NEXT_INDEX"
-then
-	USE_INDEX="$NEXT_INDEX"
-else
-	USE_INDEX="$THIS_INDEX"
-fi
-
-case "$status_only" in
-t)
-	# This will silently fail in a read-only repository, which is
-	# what we want.
-	GIT_INDEX_FILE="$USE_INDEX" git update-index -q --unmerged --refresh
-	run_status
-	exit $?
-	;;
-'')
-	GIT_INDEX_FILE="$USE_INDEX" git update-index -q --refresh || exit
-	;;
-esac
-
-################################################################
-# Grab commit message, write out tree and make commit.
-
-if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit
-then
-    GIT_INDEX_FILE="${TMP_INDEX:-${USE_INDEX}}" "$GIT_DIR"/hooks/pre-commit \
-    || exit
-fi
-
-if test "$log_message" != ''
-then
-	printf '%s\n' "$log_message"
-elif test "$logfile" != ""
-then
-	if test "$logfile" = -
-	then
-		test -t 0 &&
-		echo >&2 "(reading log message from standard input)"
-		cat
-	else
-		cat <"$logfile"
-	fi
-elif test "$use_commit" != ""
-then
-	encoding=$(git config i18n.commitencoding || echo UTF-8)
-	git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
-	sed -e '1,/^$/d' -e 's/^    //'
-elif test -f "$GIT_DIR/MERGE_MSG"
-then
-	cat "$GIT_DIR/MERGE_MSG"
-elif test -f "$GIT_DIR/SQUASH_MSG"
-then
-	cat "$GIT_DIR/SQUASH_MSG"
-elif test "$templatefile" != ""
-then
-	cat "$templatefile"
-fi | git stripspace >"$GIT_DIR"/COMMIT_EDITMSG
-
-case "$signoff" in
-t)
-	sign=$(git-var GIT_COMMITTER_IDENT | sed -e '
-		s/>.*/>/
-		s/^/Signed-off-by: /
-		')
-	blank_before_signoff=
-	tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
-	grep 'Signed-off-by:' >/dev/null || blank_before_signoff='
-'
-	tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
-	grep "$sign"$ >/dev/null ||
-	printf '%s%s\n' "$blank_before_signoff" "$sign" \
-		>>"$GIT_DIR"/COMMIT_EDITMSG
-	;;
-esac
-
-if test -f "$GIT_DIR/MERGE_HEAD" && test -z "$no_edit"; then
-	echo "#"
-	echo "# It looks like you may be committing a MERGE."
-	echo "# If this is not correct, please remove the file"
-	printf '%s\n' "#	$GIT_DIR/MERGE_HEAD"
-	echo "# and try again"
-	echo "#"
-fi >>"$GIT_DIR"/COMMIT_EDITMSG
-
-# Author
-if test '' != "$use_commit"
-then
-	eval "$(get_author_ident_from_commit "$use_commit")"
-	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
-fi
-if test '' != "$force_author"
-then
-	GIT_AUTHOR_NAME=`expr "z$force_author" : 'z\(.*[^ ]\) *<.*'` &&
-	GIT_AUTHOR_EMAIL=`expr "z$force_author" : '.*\(<.*\)'` &&
-	test '' != "$GIT_AUTHOR_NAME" &&
-	test '' != "$GIT_AUTHOR_EMAIL" ||
-	die "malformed --author parameter"
-	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
-fi
-
-PARENTS="-p HEAD"
-if test -z "$initial_commit"
-then
-	rloga='commit'
-	if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
-		rloga='commit (merge)'
-		PARENTS="-p HEAD "`sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD"`
-	elif test -n "$amend"; then
-		rloga='commit (amend)'
-		PARENTS=$(git cat-file commit HEAD |
-			sed -n -e '/^$/q' -e 's/^parent /-p /p')
-	fi
-	current="$(git rev-parse --verify HEAD)"
-else
-	if [ -z "$(git ls-files)" ]; then
-		echo >&2 'nothing to commit (use "git add file1 file2" to include for commit)'
-		exit 1
-	fi
-	PARENTS=""
-	rloga='commit (initial)'
-	current=''
-fi
-set_reflog_action "$rloga"
-
-if test -z "$no_edit"
-then
-	{
-		echo ""
-		echo "# Please enter the commit message for your changes."
-		echo "# (Comment lines starting with '#' will not be included)"
-		test -z "$only_include_assumed" || echo "$only_include_assumed"
-		run_status
-	} >>"$GIT_DIR"/COMMIT_EDITMSG
-else
-	# we need to check if there is anything to commit
-	run_status >/dev/null
-fi
-if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ]
-then
-	rm -f "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
-	use_status_color=t
-	run_status
-	exit 1
-fi
-
-case "$no_edit" in
-'')
-	git-var GIT_AUTHOR_IDENT > /dev/null  || die
-	git-var GIT_COMMITTER_IDENT > /dev/null  || die
-	git_editor "$GIT_DIR/COMMIT_EDITMSG"
-	;;
-esac
-
-case "$verify" in
-t)
-	if test -x "$GIT_DIR"/hooks/commit-msg
-	then
-		"$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG || exit
-	fi
-esac
-
-if test -z "$no_edit"
-then
-    sed -e '
-        /^diff --git a\/.*/{
-	    s///
-	    q
-	}
-	/^#/d
-    ' "$GIT_DIR"/COMMIT_EDITMSG
-else
-    cat "$GIT_DIR"/COMMIT_EDITMSG
-fi |
-git stripspace >"$GIT_DIR"/COMMIT_MSG
-
-# Test whether the commit message has any content we didn't supply.
-have_commitmsg=
-grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
-	git stripspace > "$GIT_DIR"/COMMIT_BAREMSG
-
-# Is the commit message totally empty?
-if test -s "$GIT_DIR"/COMMIT_BAREMSG
-then
-	if test "$templatefile" != ""
-	then
-		# Test whether this is just the unaltered template.
-		if cnt=`sed -e '/^#/d' < "$templatefile" |
-			git stripspace |
-			diff "$GIT_DIR"/COMMIT_BAREMSG - |
-			wc -l` &&
-		   test 0 -lt $cnt
-		then
-			have_commitmsg=t
-		fi
-	else
-		# No template, so the content in the commit message must
-		# have come from the user.
-		have_commitmsg=t
-	fi
-fi
-
-rm -f "$GIT_DIR"/COMMIT_BAREMSG
-
-if test "$have_commitmsg" = "t"
-then
-	if test -z "$TMP_INDEX"
-	then
-		tree=$(GIT_INDEX_FILE="$USE_INDEX" git write-tree)
-	else
-		tree=$(GIT_INDEX_FILE="$TMP_INDEX" git write-tree) &&
-		rm -f "$TMP_INDEX"
-	fi &&
-	commit=$(git commit-tree $tree $PARENTS <"$GIT_DIR/COMMIT_MSG") &&
-	rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
-	git update-ref -m "$GIT_REFLOG_ACTION: $rlogm" HEAD $commit "$current" &&
-	rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" &&
-	if test -f "$NEXT_INDEX"
-	then
-		mv "$NEXT_INDEX" "$THIS_INDEX"
-	else
-		: ;# happy
-	fi
-else
-	echo >&2 "* no commit message?  aborting commit."
-	false
-fi
-ret="$?"
-rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
-
-cd_to_toplevel
-
-git rerere
-
-if test "$ret" = 0
-then
-	git gc --auto
-	if test -x "$GIT_DIR"/hooks/post-commit
-	then
-		"$GIT_DIR"/hooks/post-commit
-	fi
-	if test -z "$quiet"
-	then
-		commit=`git diff-tree --always --shortstat --pretty="format:%h: %s"\
-		       --summary --root HEAD --`
-		echo "Created${initial_commit:+ initial} commit $commit"
-	fi
-fi
-
-exit "$ret"
diff --git a/git.c b/git.c
index 4e10581..8522095 100644
--- a/git.c
+++ b/git.c
@@ -298,6 +298,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
 		{ "cherry", cmd_cherry, RUN_SETUP },
 		{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
+		{ "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
 		{ "commit-tree", cmd_commit_tree, RUN_SETUP },
 		{ "config", cmd_config },
 		{ "count-objects", cmd_count_objects, RUN_SETUP },
@@ -346,10 +347,10 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "rev-parse", cmd_rev_parse, RUN_SETUP },
 		{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
 		{ "rm", cmd_rm, RUN_SETUP | NEED_WORK_TREE },
-		{ "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE },
 		{ "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
 		{ "show-branch", cmd_show_branch, RUN_SETUP },
 		{ "show", cmd_show, RUN_SETUP | USE_PAGER },
+		{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 		{ "stripspace", cmd_stripspace },
 		{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 		{ "tag", cmd_tag, RUN_SETUP },
diff --git a/strbuf.h b/strbuf.h
index 9b9e861..9720826 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -113,5 +113,6 @@ extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
 extern int strbuf_getline(struct strbuf *, FILE *, int);
 
 extern void stripspace(struct strbuf *buf, int skip_comments);
+extern void launch_editor(const char *path, struct strbuf *buffer);
 
 #endif /* STRBUF_H */
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 552af1c..2dbe04f 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -44,7 +44,7 @@ test_expect_success setup '
 test_expect_success 'cherry-pick after renaming branch' '
 
 	git checkout rename2 &&
-	EDITOR=: VISUAL=: git cherry-pick added &&
+	git cherry-pick added &&
 	test -f opos &&
 	grep "Add extra line at the end" opos
 
@@ -53,7 +53,7 @@ test_expect_success 'cherry-pick after renaming branch' '
 test_expect_success 'revert after renaming branch' '
 
 	git checkout rename1 &&
-	EDITOR=: VISUAL=: git revert added &&
+	git revert added &&
 	test -f spoo &&
 	! grep "Add extra line at the end" spoo
 
diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 28e9e37..235f372 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -154,7 +154,7 @@ test_expect_success 'cherry-pick(U/U)' '
 	git reset --hard master &&
 	git cherry-pick side^ &&
 	git cherry-pick side &&
-	EDITOR=: VISUAL=: git revert HEAD &&
+	git revert HEAD &&
 
 	check_encoding 3
 '
@@ -169,7 +169,7 @@ test_expect_success 'cherry-pick(L/L)' '
 	git reset --hard master &&
 	git cherry-pick side^ &&
 	git cherry-pick side &&
-	EDITOR=: VISUAL=: git revert HEAD &&
+	git revert HEAD &&
 
 	check_encoding 3 8859
 '
@@ -184,7 +184,7 @@ test_expect_success 'cherry-pick(U/L)' '
 	git reset --hard master &&
 	git cherry-pick side^ &&
 	git cherry-pick side &&
-	EDITOR=: VISUAL=: git revert HEAD &&
+	git revert HEAD &&
 
 	check_encoding 3
 '
@@ -200,7 +200,7 @@ test_expect_success 'cherry-pick(L/U)' '
 	git reset --hard master &&
 	git cherry-pick side^ &&
 	git cherry-pick side &&
-	EDITOR=: VISUAL=: git revert HEAD &&
+	git revert HEAD &&
 
 	check_encoding 3 8859
 '
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 714de6e..51cbcc1 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -9,8 +9,8 @@ LC_ALL=C
 PAGER=cat
 TZ=UTC
 export LANG LC_ALL PAGER TZ
-EDITOR=:
-VISUAL=:
+EDITOR=/bin/true
+VISUAL=/bin/true
 unset GIT_EDITOR
 unset AUTHOR_DATE
 unset AUTHOR_EMAIL
-- 
1.5.3.4.206.g58ba4

^ permalink raw reply related

* Re: What's cooking in git.git (topics)
From: Geert Bosch @ 2007-11-01 19:19 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.LFD.0.999.0711011129460.3342@woody.linux-foundation.org>

On Nov 1, 2007, at 14:33, Linus Torvalds wrote:
> I certainly think this should go in, but it does make one deficiency
> painfully clear: the remaining shell scripts end up having all the old
> flags behaviour.
>
> So while you can combine flags for *most* programs, you still won't
> be able to say things like
>
> 	git clean -qdx
>
> just because that's still a shellscript, and doing any fancy argument
> parsing in shell is just painful.
>
> Is somebody still working on doing the shell->C conversion?


This is by far the most dangerous command we have at this stage,
and just too easy to execute by accident. While I now have found
out that it is possible to set clean.requireForce to disarm the
command, that's the wrong way around. Only experienced users set
it, and the mere existence of the config item indicates people
do get hosed (and lose data) as a result of the poor semantics.

I often type "make clean" as well many "git xyz" commands
during development, and so it happens that at times, I type
"git clean" by accident.

So, I propose *not* converting git clean to a C builtin,
but instead adding --untracked and --ignored options to
git-rm.

This fixes two usability issues:
   1. data loss due to command typo
   2. too many git commands

Those who care about "git clean" can setup an alias
to make git clean equal to "git rm --untracked"

   -Geert

PS. No patch yet, but I wanted to prevent others from spending
     time on builtin git-clean.

^ permalink raw reply

* Re: What's cooking in git.git (topics)
From: Linus Torvalds @ 2007-11-01 18:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmytycykt.fsf@gitster.siamese.dyndns.org>



On Wed, 31 Oct 2007, Junio C Hamano wrote:
> 
> * ph/parseopt (Tue Oct 30 14:15:21 2007 -0500) 23 commits
>  + ...
> 
> It appears 1.5.4 will be, to a certain extent, a "Let's clean up
> the internal implementation" release.  This series should become
> part of it.  Hopefully will merge to 'master' soon, but I
> haven't looked this series very closely yet.

I certainly think this should go in, but it does make one deficiency 
painfully clear: the remaining shell scripts end up having all the old 
flags behaviour.

So while you can combine flags for *most* programs, you still won't 
be able to say things like

	git clean -qdx

just because that's still a shellscript, and doing any fancy argument 
parsing in shell is just painful.

Is somebody still working on doing the shell->C conversion?

		Linus

^ permalink raw reply

* Re: Importing svn branch
From: Sean @ 2007-11-01 17:23 UTC (permalink / raw)
  To: LCID Fire; +Cc: git
In-Reply-To: <4729F58C.3090706@gmx.net>

On Thu, November 1, 2007 10:49 am, LCID Fire said:
> Could anyone give me an example how to import this branch:
> svn.gnome.org/svn/banshee/branches/banshee/stable
>
> I tried git-svnimport -v -T banshee/stable/ -o master
> http://svn.gnome.org/svn/banshee
> and he imports a lot - but not the branch I want. Seems like I'm missing
> something :(

On Thu, November 1, 2007 10:49 am, LCID Fire said:
> Could anyone give me an example how to import this branch:
> svn.gnome.org/svn/banshee/branches/banshee/stable
>
> I tried git-svnimport -v -T banshee/stable/ -o master
> http://svn.gnome.org/svn/banshee
> and he imports a lot - but not the branch I want. Seems like I'm missing
> something :(
>
>

git-svnimport should probably be officially deprecated; you're not the
first person to struggle with it.  Fortunately there's another option
provided with Git which will likely give you what you're looking for:

   git svn clone http://svn.gnome.org/svn/banshee/branches/banshee/stable

Good luck,
Sean

^ permalink raw reply

* Re: [PATCH 10/10] push: teach push to be quiet if local ref is strict subset of remote ref
From: Steffen Prohaska @ 2007-11-01 16:43 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: Junio C Hamano, git
In-Reply-To: <47299855.9010204@op5.se>


On Nov 1, 2007, at 10:11 AM, Andreas Ericsson wrote:

> Steffen Prohaska wrote:
>> On Oct 31, 2007, at 10:31 PM, Junio C Hamano wrote:
>>> Steffen Prohaska <prohaska@zib.de> writes:
>>>
>>>> Another difference is the way changes are integrated. In
>>>> a workflow without shared repositories, only pull is used
>>>> for integration, while push in only used for publishing the
>>>> changes.
>>>
>>> Wrong.  push is a mirror of fetch and does not do _any_
>>> integration.  It is just a safe (because it insists on
>>> fast-forward) propagation mechanism.  Your integration still
>>> happens with pull (actually, shared repository people seem to
>>> prefer "fetch + rebase" over "pull" which is "fetch + merge").
>> Right; but you can't push without doing the integration. If you
>> have new changes on the remote side you _must_ pull before
>> you can push.
>
> Yes, because otherwise you'd rewrite published history. That's not
> a good thing.
>
>> You're forced to do the integration immediately.
>
> Yes, but you get to choose how. Perhaps git-push should list more
> options than just git-pull, such as the three commands required to
> rebase the currently checked out branch onto its remote counterpart.
> That would support more workflows.

I agree. Providing better hints would be good.


>> Your main objective was to push, but the shared workflow forces
>> you to do the integration _now_ (by using pull). In a pull-only
>> workflow, you can just push and defer the integration for later.
>
> No, you can also fetch + rebase.

Right. My point was than one cannot defer the integration. It
must be addressed immediately.


>> Some people claim fetch + rebase is superior to fetch + merge.
>> The only point I can see is that fetch + rebase gives a linear
>> history without loops, which is nicer to visualize. I recently
>> asked on the list if there are any benefits of fetch + rebase
>> over fetch + merge, besides a nicer visualization.
>
>
> It's easier to bisect. If git bisect lands you on a merge-commit,
> you need to start a new bisect for each of the parents included
> in the merge. Hopefully the nature of the merge gives a clue so
> the user can make an educated guess as to which parent introduced
> the bogus commit, but for an "evil octopus" (unusual) or if the
> merge had conflicts which were resolved in a buggy way (not
> exactly uncommon), it can be quite a hassle to get things right.
> With a mostly linear history, this problem goes away.

This is really an interesting point. I did not start to use
git bisect regularly. But I certainly plan to do so in the future.

Couldn't bisect learn to better cope with non-linear history?

[...]


>> I am searching for a solution that just works for them. They
>> currently use CVS. I'll give them a detailed getting started
>> document for git. The workflow described should be as simple as
>> possible, but safe and reliable.
>
>
> If they're used to CVS and want to use more than one branch without
> having to learn additional syntax, nothing can help, methinks.

They will learn. But they must not get frustrated too early.
I also don't wont to see them lining up in front of my office.


BTW, what do you thing about the proposal to add branch.$name.push [1]?

[1] http://marc.info/?l=git&m=119384331712996&w=2


[...]

>> There were different suggestions what to do. A reasonable
>> suggestion was to delete the local branch after you're done.
>
> Except that it doesn't work unless you either detach the HEAD
> (which prints a big fat ugly message) or give it -D to force
> it, which I really, really don't recommend. We use git because
> I'm pretty confident in its capabilities of never ever losing
> anything. Using the seemingly harmless -D switch to git-branch
> puts us at risk of wiping history quite without noticing.

I don't like -D either. I liked the idea mentioned recently
to check -d against the remotes. If a remote tracking branch
has the history it should be considered fully merged.

Another idea may be to distinguish between detached head and
checkout of remote tracking branch. Maybe we could do some
useful things if get knew that the user is 'on a remote tracking
branch'. Committing could be forbidden. A suggestion would be
printed instead to use "git checkout -b something", which could act
as if the remote branch was mentioned on the command line.

Something like that would be needed before I'd seriously
suggest to delete local branches after you finished your work.


>> This clearly distinguishes between remote branches (which are
>> mirrored as a remote tracking branch) and local branches. Local
>> branches are _your_ branches while the remote branches contain
>> the shared work. If you're done with your local work, delete
>> your local branch. So maybe you should do
>>    git checkout origin/devel
>
> Except that this gives a warning-esque message:
> Note: moving to "origin/devel" which isn't a local branch
> If you want to create a new branch from this checkout, you may do so
> (now or later) by using -b with the checkout command again. Example:
>  git checkout -b <new_branch_name>
> HEAD is now at deadbeef... Ma! Pa butchered all the cows!
>
> To me, this indicates I've done something git thinks I shouldn't have.

I agree. This could probably be suppressed if git handled remote
tracking branches a bit differently from other detached heads.


>> Independently of what the best practice is, leaving the local
>> work branch there shouldn't do any harm because I'm sure that
>> some devs will forget to clean up, independently of what I tell
>> them.
>
> I wholeheartedly agree with this one.

So I think we need to resolve this first.

Do you already have post-checkout script that makes useful
suggestions.  I remember you mentioned something like that
during the 200-local-branches discussion.

	Steffen

^ permalink raw reply

* Re: New features in gitk
From: Linus Torvalds @ 2007-11-01 16:21 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <alpine.LFD.0.999.0711010844260.3342@woody.linux-foundation.org>



On Thu, 1 Nov 2007, Linus Torvalds wrote:
> 
> The hot-cache numbers are already pretty damn good. But try this:
> 
> 	echo 3 > /proc/sys/vm/drop_caches
> 	gitk

Actually, do the above with a path limiter, to make it more obvious.

So try this on the kernel, and you'll see the difference even with a fast 
disk, and even if it's fully packed:

	echo 3 > /proc/sys/vm/drop_caches
	time git rev-list HEAD drivers/scsi | head -10

and now try it with --topo-order.

I get ten seconds with --topo-order (because it has to traverse the 
*whole* history even to just generate the first ten lines), while the 
non-topo-order case is *three*times* faster.

On my laptop, it's even more noticeable. I don't know quite why, but the 
non-topo-order case is actually faster on my laptop than on my desktop 
(will have to see what's up, but I suspect it's a result of they being at 
different points in history, and just bad luck wrt the top-of-history 
having happened to change drivers/scsi or not):

	[torvalds@t40 linux]$ time git rev-list HEAD drivers/scsi | head -10
	..
	real    0m0.688s

but with --topo-order it's much slower:

	[torvalds@t40 linux]$ time git rev-list --topo-order HEAD drivers/scsi | head -10
	..
	real    0m17.458s

See? You shouldn't care about CPU usage, you should care about IO costs! 
Those are the first-order effects.

In other words, if you can be incremental, we're talking about performance 
differences that are orders-of-magnitude. Not ten percent or something 
piddling like that! And the performance improvemens come for the cases 
that are the _problem_, rather than the cases that already work perfectly 
well.

				Linus

^ permalink raw reply

* Importing svn branch
From: LCID Fire @ 2007-11-01 15:49 UTC (permalink / raw)
  To: git

Could anyone give me an example how to import this branch:
svn.gnome.org/svn/banshee/branches/banshee/stable

I tried git-svnimport -v -T banshee/stable/ -o master
http://svn.gnome.org/svn/banshee
and he imports a lot - but not the branch I want. Seems like I'm missing
something :(

^ permalink raw reply

* Re: New features in gitk
From: Linus Torvalds @ 2007-11-01 15:47 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <18217.47744.621850.100789@cargo.ozlabs.ibm.com>



On Thu, 1 Nov 2007, Paul Mackerras wrote:
>
> Linus Torvalds writes: 
> > The cost is not generally in outputting the commits. The real cost is in 
> > traversing them in the first place. 
> 
> Actually, the biggest cost is still gitk reading in the commits from
> git log and doing the processing that gitk needs to do on each commit
> (which I have tried to minimize, and is way smaller than it used to
> be, but is still significant).

Umm. I think you're basing all your timings on hot-cache numbers.

The hot-cache numbers are already pretty damn good. But try this:

	echo 3 > /proc/sys/vm/drop_caches
	gitk

on a big repository, _especially_ one that isn't totally packed, or on a 
machine with a slow laptop disk. Just following the commit history is 
really quite expensive.

THAT is the problem with --topo-order.

			Linus

^ permalink raw reply

* Re: Where man git-format-patch sends me?
From: Sergei Organov @ 2007-11-01 15:47 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0711011437440.4362@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Hi,
>
> On Thu, 1 Nov 2007, Sergei Organov wrote:
>
>> $ man git-format-patch
>> [...]
>> OPTIONS
>>        -p     Generate patch (see section on generating patches)
>> 
>>        -u     Synonym for "-p".
>
> As you can easily see from Documentation/git-format-patch.txt, this part 
> is generated from the file Documentation/diff-options.txt.

Sorry, I did saw that, but it doesn't change anything.

1. As a user reading man git-format-patch, where do I find this "section
   on generating patches"? In another man-page? In the html
   documentation? On the moon?

2. I can't find "section on generating patches" in the man git-diff
   either, and I did say this in the part of my original message you've
   snipped.

So the main question remains: could you please point me to the exact
place in 'Documentation/' directory where this "section on generating
patches" resides?

-- 
Sergei.

^ permalink raw reply

* Re: Managing /etc with git: Store ownership and time in git?
From: Jakub Narebski @ 2007-11-01 15:42 UTC (permalink / raw)
  To: git
In-Reply-To: <20071101130928.GH27987@genesis.frugalware.org>

Miklos Vajna wrote:

> On Thu, Nov 01, 2007 at 12:55:57PM +0000, Alexander Skwar <listen@alexander.skwar.name> wrote:
>> I'd like to use git to manage the /etc directories of some servers.
> 
> http://git.or.cz/gitwiki/GitFaq#head-7e70881352ec207609dc4d7eedbd0532946a5825

http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
search for Metastore

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Document that using -M without other diff options is not a good idea
From: Miklos Vajna @ 2007-11-01 15:24 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0711011508490.4362@racer.site>

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

On Thu, Nov 01, 2007 at 03:09:25PM +0000, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> As I remarked on IRC earlier, this will also show up in the man page of 
> git-diff, too.  Rather funny, no?

ah, then i misunderstood you. so the correct way would be to juse ignore
the -M switch if it's useless? my problem is that if you use git log -M
then it's a pointless slowdown and you can't find this in the doc :s

thanks,
- VMiklos

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: New features in gitk
From: Linus Torvalds @ 2007-11-01 15:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <18217.41899.54812.227152@cargo.ozlabs.ibm.com>



On Thu, 1 Nov 2007, Paul Mackerras wrote:
> 
> The other thing --topo-order does is reorder the commits so that
> related commits come together.

If that's the only reason for using it, then please stop, and use 
"--first-parent" instead.

		Linus

^ permalink raw reply

* Re: Newbie: report of first experience with git-rebase.
From: J. Bruce Fields @ 2007-11-01 15:10 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Sergei Organov, Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0711011423440.4362@racer.site>

On Thu, Nov 01, 2007 at 02:24:37PM +0000, Johannes Schindelin wrote:
> Hi,
> 
> On Thu, 1 Nov 2007, Sergei Organov wrote:
> 
> > Junio C Hamano <gitster@pobox.com> writes:
> > 
> > > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> > >
> > >> On Wed, 31 Oct 2007, Sergei Organov wrote:
> > >>
> > >>> Yes, and that's the problem. Why 'git --continue' didn't just skip this 
> > >>> patch that *already became no-op* after conflict resolution and forced 
> > >>> me to explicitly use 'git --skip' instead?
> > >>
> > >> Isn't that obvious?  To prevent you from accidentally losing a commit.
> > >
> > > In case it is not obvious...
> > >
> > > A rebase conflict resolution that results in emptiness is a
> > > rather rare event (especially because rebase drops upfront the
> > > identical changes from the set of commits to be replayed), but
> > > it does happen.
> > 
> > Funny how 2 of my first 3 commits suffer from this "rather rare event",
> > and it was not Friday, 13 ;)
> 
> They are rare events.  In your case I guess that subtly different versions 
> were _actually_ applied (such as white space fixes),

That's actually pretty common, in my experience.

> which is why such a rare event hit you.

I'm using git to track some changes I submitted to a project that's
mainly text, and that I only get release tarballs of.  On my most recent
rebase all my patches got applied, but the text also got re-wrapped and
re-indented at the same time.  So all but I think one or two of a dozen
patches ended up with a conflict resolution and then --skip.

Which may not be a case git's really intended for--fair enough.  But
I've found it's pretty common in my kernel work too.  Either I'm
rebasing against changes I made myself, or else a maintainer took my
changes but fixed up some minor style problems along the way.

--b.

^ permalink raw reply

* Re: [PATCH] Document that using -M without other diff options is not a good idea
From: Johannes Schindelin @ 2007-11-01 15:09 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: Junio C Hamano, git
In-Reply-To: <1193929060-6183-1-git-send-email-vmiklos@frugalware.org>

Hi,

On Thu, 1 Nov 2007, Miklos Vajna wrote:

> Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
> ---
> 
> I just noticed that I used 'git log -M' in some scripts which is obviously bad.
> People should not use that option without other diff options.
> 
>  Documentation/diff-options.txt |    4 +++-
>  1 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
> index b1f528a..ed827f8 100644
> --- a/Documentation/diff-options.txt
> +++ b/Documentation/diff-options.txt
> @@ -92,7 +92,9 @@
>  	Break complete rewrite changes into pairs of delete and create.
>  
>  -M::
> -	Detect renames.
> +	Detect renames. It's no good using this option if you don't use diff
> +	options like `--name-status`, `-p` or `--stat` as it will just slow
> +	down the revision walker.

As I remarked on IRC earlier, this will also show up in the man page of 
git-diff, too.  Rather funny, no?

Ciao,
Dscho

^ permalink raw reply

* [PATCH] Document that using -M without other diff options is not a good idea
From: Miklos Vajna @ 2007-11-01 14:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Miklos Vajna, git

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

I just noticed that I used 'git log -M' in some scripts which is obviously bad.
People should not use that option without other diff options.

 Documentation/diff-options.txt |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index b1f528a..ed827f8 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -92,7 +92,9 @@
 	Break complete rewrite changes into pairs of delete and create.
 
 -M::
-	Detect renames.
+	Detect renames. It's no good using this option if you don't use diff
+	options like `--name-status`, `-p` or `--stat` as it will just slow
+	down the revision walker.
 
 -C::
 	Detect copies as well as renames.  See also `--find-copies-harder`.
-- 
1.5.3.5

^ permalink raw reply related

* [PATCH] Include diff options in the git-log manpage
From: Miklos Vajna @ 2007-11-01 14:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Miklos Vajna, git
In-Reply-To: <1193929060-6183-1-git-send-email-vmiklos@frugalware.org>

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

Recently I wanted to see what git log -M does but actually I was not able to
find it in the manpage, finally figured out that all the diff options are
missing from here.

Removing -p as it's already in diff-options.txt.

If this patch OK, then I would like to send a similar patch to
git-rev-list.txt, too.

 Documentation/git-log.txt |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 5ec547c..4b1b982 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -27,6 +27,8 @@ OPTIONS
 
 include::pretty-options.txt[]
 
+include::diff-options.txt[]
+
 -<n>::
 	Limits the number of commits to show.
 
@@ -43,9 +45,6 @@ include::pretty-options.txt[]
 	commit.  This  option gives a better overview of the
 	evolution of a particular branch.
 
--p::
-	Show the change the commit introduces in a patch form.
-
 -g, \--walk-reflogs::
 	Show commits as they were recorded in the reflog. The log contains
 	a record about how the tip of a reference was changed.
-- 
1.5.3.5

^ permalink raw reply related


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