* Re: History over-simplification
From: linux @ 2007-09-27 4:56 UTC (permalink / raw)
To: git, spearce; +Cc: gitster, linux
>> b) The resulting path matches one of the parents but not one of
>> the others. In such a case the merge should still be output if
>> a 3-way read-tree would not have chosen this result by default.
> I am not sure (b) is useful in general. Merging two branches
> that fix the same issue but in different ways (think: 'maint'
> and 'master' have different infrastructure and a fix initially
> made on 'master' was backported to 'maint', and then later
> 'maint' needed to be merged to 'master' to carry forward other
> fixes) is a norm, and in such cases taking the version from the
> merged-to branch is almost always what happens.
>
> Also it sounds to me by "if read-tree would not have chosen this
> result by default" you mean this feature would not just need to
> run merge-base but also recursive merge-base synthesis, and also
> recreate the structural merge (aka "rename detection") there as
> well. Even if (b) is useful, it sounds like a very expensive
> option, and the current merge-recursive code is structured in
> such a way to be easily reused for this purpose.
These seem like roundabout ways of expressing the requirement.
The desired rule is "no silent changes in the simplified history".
E.g. if the revision history of a particular file is:
+-C-+
/ \
A---B B---D
\ /
+-B-+
Then the normal code will notice that there are no changes on the
lower branch, prune the merge entirely, and simplify to A---B---C---D.
This is, however, misleading; the true history is A---B---C---B---D.
A merge must be shown unless it matches a *non-eliminated* ancestor.
The point is that this isn't expressed in terms of what merge-base would
do, but in terms of what the path limiter is in the process of doing.
Now, I haven't dived into the Deep Magic of revision.c to figure out
where to put this into the code, unfortunately.
Another way to say it is that the desired simplified history
is achieved when you have exhausted the following two rules:
- You may delete any revision which has only one ancestor and
is identical (after path-limiting) to that ancestor.
(Descendants are implicitly linked to that ancestor.)
- You may delete any ancestor link A---B if there is an
alternative directed path between A and B.
(Fast-forward rule.)
Given unlabeled ancestor links, there is a unique fixed point.
The current code is willing to delete a revision that is
identical to *any* ancestor, even deleted ones.
^ permalink raw reply
* Re: [PATCH] Add --no-rename to git-apply
From: Junio C Hamano @ 2007-09-27 5:12 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git
In-Reply-To: <11908420041596-git-send-email-robin.rosenberg@dewire.com>
Robin Rosenberg <robin.rosenberg@dewire.com> writes:
> With this option git-apply can apply a patch with a rename
> onto the original file(s).
This is troubling from both design and implementation point of
view.
* Why would this be useful? What's the point of producing the
renaming patch if you know you would want to apply while
ignoring the rename?
* The change looks too special purpose to me. If you are
giving the ability to deposit the result to somewhere other
than where the patch intendes to, why limit it only to the
preimage name? Aren't there cases where A is renamed to B
sometime in the history, and you have a patch that talks
about the content change A->A but the tree you have has the
contents already in B, and you would want to apply that
patch? It feels that this and your "ignore rename" could be
handled much more cleanly and flexibly by preprocessing the
patchfile.
* By disabling the parsing of rename header lines, you are
disabling the sanity checking of the input done in
gitdiff_verify_name() called from gitdiff_oldname() and
gitdiff_newname(). I think it is wrong for --no-rename
option to affect the parsing of the input. If we were to do
this, perhaps write_out_results() or one of its callee would
be a better place to do so.
^ permalink raw reply
* [PATCH 4/4] Move launch_editor() and stripspace() to new file editor.c.
From: Kristian Høgsberg @ 2007-09-27 4:50 UTC (permalink / raw)
To: gitster; +Cc: git, Kristian Høgsberg
In-Reply-To: <1190868632-29287-3-git-send-email-krh@redhat.com>
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
Makefile | 2 +-
builtin-commit.c | 1 +
builtin-stripspace.c | 68 +------------------------------
builtin-tag.c | 40 +------------------
editor.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++
editor.h | 9 ++++
strbuf.h | 3 -
7 files changed, 122 insertions(+), 110 deletions(-)
create mode 100644 editor.c
create mode 100644 editor.h
diff --git a/Makefile b/Makefile
index 6172589..f6d991e 100644
--- a/Makefile
+++ b/Makefile
@@ -310,7 +310,7 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
- transport.o bundle.o parse-options.o
+ transport.o bundle.o parse-options.o editor.o
BUILTIN_OBJS = \
builtin-add.o \
diff --git a/builtin-commit.c b/builtin-commit.c
index 69e8b19..7d87812 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -19,6 +19,7 @@
#include "strbuf.h"
#include "utf8.h"
#include "parse-options.h"
+#include "editor.h"
static const char builtin_commit_usage[] =
"[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]";
diff --git a/builtin-stripspace.c b/builtin-stripspace.c
index c0b2130..4e5bb07 100644
--- a/builtin-stripspace.c
+++ b/builtin-stripspace.c
@@ -1,72 +1,6 @@
#include "builtin.h"
#include "cache.h"
-
-/*
- * Returns the length of a line, without trailing spaces.
- *
- * If the line ends with newline, it will be removed too.
- */
-static size_t cleanup(char *line, size_t len)
-{
- while (len) {
- unsigned char c = line[len - 1];
- if (!isspace(c))
- break;
- len--;
- }
-
- return len;
-}
-
-/*
- * Remove empty lines from the beginning and end
- * and also trailing spaces from every line.
- *
- * Note that the buffer will not be NUL-terminated.
- *
- * Turn multiple consecutive empty lines between paragraphs
- * into just one empty line.
- *
- * If the input has only empty lines and spaces,
- * no output will be produced.
- *
- * If last line does not have a newline at the end, one is added.
- *
- * Enable skip_comments to skip every line starting with "#".
- */
-void stripspace(struct strbuf *sb, int skip_comments)
-{
- int empties = 0;
- size_t i, j, len, newlen;
- char *eol;
-
- /* We may have to add a newline. */
- strbuf_grow(sb, 1);
-
- for (i = j = 0; i < sb->len; i += len, j += newlen) {
- eol = memchr(sb->buf + i, '\n', sb->len - i);
- len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
-
- if (skip_comments && len && sb->buf[i] == '#') {
- newlen = 0;
- continue;
- }
- newlen = cleanup(sb->buf + i, len);
-
- /* Not just an empty line? */
- if (newlen) {
- if (empties > 0 && j > 0)
- sb->buf[j++] = '\n';
- empties = 0;
- memmove(sb->buf + j, sb->buf + i, newlen);
- sb->buf[newlen + j++] = '\n';
- } else {
- empties++;
- }
- }
-
- strbuf_setlen(sb, j);
-}
+#include "editor.h"
int cmd_stripspace(int argc, const char **argv, const char *prefix)
{
diff --git a/builtin-tag.c b/builtin-tag.c
index 0a36a5d..c9a0497 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -10,6 +10,7 @@
#include "builtin.h"
#include "refs.h"
#include "tag.h"
+#include "editor.h"
#include "run-command.h"
static const char builtin_tag_usage[] =
@@ -17,45 +18,6 @@ static const char builtin_tag_usage[] =
static char signingkey[1000];
-void launch_editor(const char *path, struct strbuf *buffer)
-{
- const char *editor, *terminal;
- struct child_process child;
- const char *args[3];
-
- editor = getenv("GIT_EDITOR");
- if (!editor && editor_program)
- editor = editor_program;
- if (!editor)
- editor = getenv("VISUAL");
- if (!editor)
- editor = getenv("EDITOR");
-
- terminal = getenv("TERM");
- if (!editor && (!terminal || !strcmp(terminal, "dumb"))) {
- fprintf(stderr,
- "Terminal is dumb but no VISUAL nor EDITOR defined.\n"
- "Please supply the message using either -m or -F option.\n");
- exit(1);
- }
-
- if (!editor)
- editor = "vi";
-
- memset(&child, 0, sizeof(child));
- child.argv = args;
- args[0] = editor;
- args[1] = path;
- args[2] = NULL;
-
- if (run_command(&child))
- die("There was a problem with the editor %s.", editor);
-
- if (strbuf_read_file(buffer, path) < 0)
- die("could not read message file '%s': %s",
- path, strerror(errno));
-}
-
struct tag_filter {
const char *pattern;
int lines;
diff --git a/editor.c b/editor.c
new file mode 100644
index 0000000..6bc3033
--- /dev/null
+++ b/editor.c
@@ -0,0 +1,109 @@
+#include "git-compat-util.h"
+#include "editor.h"
+#include "run-command.h"
+
+void launch_editor(const char *path, struct strbuf *buffer)
+{
+ const char *editor, *terminal;
+ struct child_process child;
+ const char *args[3];
+
+ editor = getenv("GIT_EDITOR");
+ if (!editor && editor_program)
+ editor = editor_program;
+ if (!editor)
+ editor = getenv("VISUAL");
+ if (!editor)
+ editor = getenv("EDITOR");
+
+ terminal = getenv("TERM");
+ if (!editor && (!terminal || !strcmp(terminal, "dumb"))) {
+ fprintf(stderr,
+ "Terminal is dumb but no VISUAL nor EDITOR defined.\n"
+ "Please supply the message using either -m or -F option.\n");
+ exit(1);
+ }
+
+ if (!editor)
+ editor = "vi";
+
+ memset(&child, 0, sizeof(child));
+ child.argv = args;
+ args[0] = editor;
+ args[1] = path;
+ args[2] = NULL;
+
+ if (run_command(&child))
+ die("There was a problem with the editor %s.", editor);
+
+ if (strbuf_read_file(buffer, path) < 0)
+ die("could not read message file '%s': %s",
+ path, strerror(errno));
+}
+
+/*
+ * Returns the length of a line, without trailing spaces.
+ *
+ * If the line ends with newline, it will be removed too.
+ */
+static size_t cleanup(char *line, size_t len)
+{
+ while (len) {
+ unsigned char c = line[len - 1];
+ if (!isspace(c))
+ break;
+ len--;
+ }
+
+ return len;
+}
+
+/*
+ * Remove empty lines from the beginning and end
+ * and also trailing spaces from every line.
+ *
+ * Note that the buffer will not be NUL-terminated.
+ *
+ * Turn multiple consecutive empty lines between paragraphs
+ * into just one empty line.
+ *
+ * If the input has only empty lines and spaces,
+ * no output will be produced.
+ *
+ * If last line does not have a newline at the end, one is added.
+ *
+ * Enable skip_comments to skip every line starting with "#".
+ */
+void stripspace(struct strbuf *sb, int skip_comments)
+{
+ int empties = 0;
+ size_t i, j, len, newlen;
+ char *eol;
+
+ /* We may have to add a newline. */
+ strbuf_grow(sb, 1);
+
+ for (i = j = 0; i < sb->len; i += len, j += newlen) {
+ eol = memchr(sb->buf + i, '\n', sb->len - i);
+ len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
+
+ if (skip_comments && len && sb->buf[i] == '#') {
+ newlen = 0;
+ continue;
+ }
+ newlen = cleanup(sb->buf + i, len);
+
+ /* Not just an empty line? */
+ if (newlen) {
+ if (empties > 0 && j > 0)
+ sb->buf[j++] = '\n';
+ empties = 0;
+ memmove(sb->buf + j, sb->buf + i, newlen);
+ sb->buf[newlen + j++] = '\n';
+ } else {
+ empties++;
+ }
+ }
+
+ strbuf_setlen(sb, j);
+}
diff --git a/editor.h b/editor.h
new file mode 100644
index 0000000..9dc39f5
--- /dev/null
+++ b/editor.h
@@ -0,0 +1,9 @@
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#include "cache.h"
+
+extern void launch_editor(const char *path, struct strbuf *buffer);
+extern void stripspace(struct strbuf *sb, int skip_comments);
+
+#endif
diff --git a/strbuf.h b/strbuf.h
index eef4e6d..d4d9e56 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -112,7 +112,4 @@ extern int strbuf_read_file(struct strbuf *sb, const char *path);
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 */
--
1.5.2.GIT
^ permalink raw reply related
* [PATCH 3/4] Implement git commit as a builtin command.
From: Kristian Høgsberg @ 2007-09-27 4:50 UTC (permalink / raw)
To: gitster; +Cc: git, Kristian Høgsberg
In-Reply-To: <1190868632-29287-2-git-send-email-krh@redhat.com>
Move git-commit.sh to contrib/examples.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
Makefile | 9 +-
builtin-commit.c | 611 +++++++++++++++++++++++++++++++++++++++
builtin-tag.c | 3 +-
builtin.h | 3 +-
contrib/examples/git-commit.sh | 627 ++++++++++++++++++++++++++++++++++++++++
git-commit.sh | 627 ----------------------------------------
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, 1255 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 d90e959..6172589 100644
--- a/Makefile
+++ b/Makefile
@@ -206,7 +206,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 \
@@ -254,7 +254,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
@@ -324,6 +324,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 \
@@ -362,7 +363,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 \
@@ -822,9 +822,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..69e8b19
--- /dev/null
+++ b/builtin-commit.c
@@ -0,0 +1,611 @@
+/*
+ * 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 "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 builtin_commit_usage[] =
+ "[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]";
+
+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, no_verify, amend, signoff;
+static int quiet, verbose, untracked_files;
+
+static int no_edit, initial_commit, in_merge;
+const char *only_include_assumed;
+
+static struct option commit_options[] = {
+ { OPTION_STRING, "file", 'F', (void *) &logfile },
+ { OPTION_BOOLEAN, "all", 'a', &all },
+ { OPTION_STRING, "author", 0, (void *) &force_author },
+ { OPTION_BOOLEAN, "edit", 'e', &edit_flag },
+ { OPTION_BOOLEAN, "include", 'i', &also },
+ { OPTION_BOOLEAN, "interactive", 0, &interactive },
+ { OPTION_BOOLEAN, "only", 'o', &only },
+ { OPTION_STRING, "message", 'm', &message },
+ { OPTION_BOOLEAN, "no-verify", 'n', &no_verify },
+ { OPTION_BOOLEAN, "amend", 0, &amend },
+ { OPTION_STRING, "reedit-message", 'c', &edit_message },
+ { OPTION_STRING, "reuse-message", 'C', &use_message },
+ { OPTION_BOOLEAN, "signoff", 's', &signoff },
+ { OPTION_BOOLEAN, "quiet", 'q', &quiet },
+ { OPTION_BOOLEAN, "verbose", 'v', &verbose },
+ { OPTION_BOOLEAN, "untracked-files", 0, &untracked_files },
+ { OPTION_STRING, "template", 't', &template_file },
+ { OPTION_LAST },
+};
+
+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(0, prefix, 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(fd, 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();
+ }
+
+ /*
+ * FIXME: Warn on unknown files. Shell script does
+ *
+ * commit_only=`git-ls-files --error-unmatch -- "$@"`
+ */
+
+ /*
+ * FIXME: shell script does
+ *
+ * git-read-tree --index-output="$TMP_INDEX" -i -m HEAD
+ *
+ * which warns about unmerged files in the index.
+ */
+
+ /* update the user index file */
+ add_files_to_cache(0, 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(0, 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)
+ 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)
+ 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)
+ die("could not read SQUASH_MSG: %s", strerror(errno));
+ } else if (!stat(template_file, &statbuf)) {
+ if (strbuf_read_file(&sb, template_file) < 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) {
+ 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 void parse_and_validate_options(const char ***argv)
+{
+ int f = 0;
+
+ (*argv)++;
+ while (parse_options(argv, commit_options, ARRAY_SIZE(commit_options),
+ builtin_commit_usage))
+ ;
+
+ 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 && **argv)
+ die("Paths with -a does not make sense.");
+ else if (interactive && **argv)
+ die("Paths with --interactive does not make sense.");
+}
+
+int cmd_status(int argc, const char **argv, const char *prefix)
+{
+ const char *index_file;
+ int commitable;
+
+ git_config(git_status_config);
+
+ parse_and_validate_options(&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);
+
+ parse_and_validate_options(&argv);
+
+ index_file = prepare_index(argv, prefix);
+
+ if (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)
+ 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 a1a2cf0..0a36a5d 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -17,12 +17,11 @@ 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;
const char *args[3];
- int fd;
editor = getenv("GIT_EDITOR");
if (!editor && editor_program)
diff --git a/builtin.h b/builtin.h
index 65cc0fb..470a788 100644
--- a/builtin.h
+++ b/builtin.h
@@ -23,6 +23,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);
@@ -67,10 +68,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..44ccc44
--- /dev/null
+++ b/contrib/examples/git-commit.sh
@@ -0,0 +1,627 @@
+#!/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
+}
+
+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 44ccc44..0000000
--- a/git-commit.sh
+++ /dev/null
@@ -1,627 +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
-}
-
-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 d7c6bca..9565555 100644
--- a/git.c
+++ b/git.c
@@ -320,6 +320,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 },
@@ -368,10 +369,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 5657e3d..eef4e6d 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -113,5 +113,6 @@ extern int strbuf_read_file(struct strbuf *sb, const char *path);
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 cc1253c..a232bd6 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.2.GIT
^ permalink raw reply related
* [PATCH 2/4] This exports the update() function from builtin-add.c as
From: Kristian Høgsberg @ 2007-09-27 4:50 UTC (permalink / raw)
To: gitster; +Cc: git, Kristian Høgsberg
In-Reply-To: <1190868632-29287-1-git-send-email-krh@redhat.com>
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
builtin-add.c | 8 ++++----
commit.h | 2 ++
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/builtin-add.c b/builtin-add.c
index 5e30380..966e145 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -107,7 +107,7 @@ static void update_callback(struct diff_queue_struct *q,
}
}
-static void update(int verbose, const char *prefix, const char **files)
+void add_files_to_cache(int verbose, const char *prefix, const char **files)
{
struct rev_info rev;
init_revisions(&rev, prefix);
@@ -116,8 +116,6 @@ static void update(int verbose, const char *prefix, const char **files)
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = update_callback;
rev.diffopt.format_callback_data = &verbose;
- if (read_cache() < 0)
- die("index file corrupt");
run_diff_files(&rev, 0);
}
@@ -218,7 +216,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
if (take_worktree_changes) {
- update(verbose, prefix, argv + i);
+ if (read_cache() < 0)
+ die("index file corrupt");
+ add_files_to_cache(verbose, prefix, argv + i);
goto finish;
}
diff --git a/commit.h b/commit.h
index cc8d890..89caa12 100644
--- a/commit.h
+++ b/commit.h
@@ -130,6 +130,8 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,
int in_merge_bases(struct commit *, struct commit **, int);
extern int interactive_add(void);
+extern void add_files_to_cache(int verbose,
+ const char *prefix, const char **files);
extern int rerere(void);
#endif /* COMMIT_H */
--
1.5.2.GIT
^ permalink raw reply related
* [PATCH 1/4] Add a simple option parser for use by builtin-commit.c.
From: Kristian Høgsberg @ 2007-09-27 4:50 UTC (permalink / raw)
To: gitster; +Cc: git, Kristian Høgsberg
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
Makefile | 2 +-
parse-options.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
parse-options.h | 29 +++++++++++++++++++++
3 files changed, 104 insertions(+), 1 deletions(-)
create mode 100644 parse-options.c
create mode 100644 parse-options.h
diff --git a/Makefile b/Makefile
index 62bdac6..d90e959 100644
--- a/Makefile
+++ b/Makefile
@@ -310,7 +310,7 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
- transport.o bundle.o
+ transport.o bundle.o parse-options.o
BUILTIN_OBJS = \
builtin-add.o \
diff --git a/parse-options.c b/parse-options.c
new file mode 100644
index 0000000..2fb30cd
--- /dev/null
+++ b/parse-options.c
@@ -0,0 +1,74 @@
+#include "git-compat-util.h"
+#include "parse-options.h"
+
+int parse_options(const char ***argv,
+ struct option *options, int count,
+ const char *usage_string)
+{
+ const char *value, *eq;
+ int i;
+
+ if (**argv == NULL)
+ return 0;
+ if ((**argv)[0] != '-')
+ return 0;
+ if (!strcmp(**argv, "--"))
+ return 0;
+
+ value = NULL;
+ for (i = 0; i < count; i++) {
+ if ((**argv)[1] == '-') {
+ if (!prefixcmp(options[i].long_name, **argv + 2)) {
+ if (options[i].type != OPTION_BOOLEAN)
+ value = *++(*argv);
+ goto match;
+ }
+
+ eq = strchr(**argv + 2, '=');
+ if (eq && options[i].type != OPTION_BOOLEAN &&
+ !strncmp(**argv + 2,
+ options[i].long_name, eq - **argv - 2)) {
+ value = eq + 1;
+ goto match;
+ }
+ }
+
+ if ((**argv)[1] == options[i].short_name) {
+ if ((**argv)[2] == '\0') {
+ if (options[i].type != OPTION_BOOLEAN)
+ value = *++(*argv);
+ goto match;
+ }
+
+ if (options[i].type != OPTION_BOOLEAN) {
+ value = **argv + 2;
+ goto match;
+ }
+ }
+ }
+
+ usage(usage_string);
+
+ match:
+ switch (options[i].type) {
+ case OPTION_BOOLEAN:
+ *(int *)options[i].value = 1;
+ break;
+ case OPTION_STRING:
+ if (value == NULL)
+ die("option %s requires a value.", (*argv)[-1]);
+ *(const char **)options[i].value = value;
+ break;
+ case OPTION_INTEGER:
+ if (value == NULL)
+ die("option %s requires a value.", (*argv)[-1]);
+ *(int *)options[i].value = atoi(value);
+ break;
+ default:
+ assert(0);
+ }
+
+ (*argv)++;
+
+ return 1;
+}
diff --git a/parse-options.h b/parse-options.h
new file mode 100644
index 0000000..39399c3
--- /dev/null
+++ b/parse-options.h
@@ -0,0 +1,29 @@
+#ifndef PARSE_OPTIONS_H
+#define PARSE_OPTIONS_H
+
+enum option_type {
+ OPTION_BOOLEAN,
+ OPTION_STRING,
+ OPTION_INTEGER,
+ OPTION_LAST,
+};
+
+struct option {
+ enum option_type type;
+ const char *long_name;
+ char short_name;
+ void *value;
+};
+
+/* Parse the given options against the list of known options. The
+ * order of the option structs matters, in that ambiguous
+ * abbreviations (eg, --in could be short for --include or
+ * --interactive) are matched by the first option that share the
+ * prefix.
+ */
+
+extern int parse_options(const char ***argv,
+ struct option *options, int count,
+ const char *usage_string);
+
+#endif
--
1.5.2.GIT
^ permalink raw reply related
* Re: What's cooking in git.git (topics)
From: Jeff King @ 2007-09-27 2:36 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfy11yyxk.fsf@gitster.siamese.dyndns.org>
On Wed, Sep 26, 2007 at 01:05:59PM -0700, Junio C Hamano wrote:
> * jk/diff-rename (Tue Sep 25 15:29:42 2007 -0400) 1 commit
> + diffcore-rename: cache file deltas
>
> Parked in 'next' for now but is 'master' material.
My tests after this patch show that spanhash_find is responsible for
a large portion of the processing time in large renames, so I am going
to look into speeding that up.
> * lh/merge (Mon Sep 24 00:51:45 2007 +0200) 6 commits
> + git-merge: add --ff and --no-ff options
> + git-merge: add support for --commit and --no-squash
> + git-merge: add support for branch.<name>.mergeoptions
> + git-merge: refactor option parsing
> + git-merge: fix faulty SQUASH_MSG
> + Add test-script for git-merge porcelain
>
> Comments? I personally never felt need for --no-ff but the
> series is reasonably clean so I do not see strong objection
> against this series either.
I like it. I know that --no-ff is frowned upon, but I think previous
discussions have mentioned workflows where it might be used
intelligently. Since the patch is unlikely to break anything for
traditional workflows, I think it is a nice way to let people experiment
with alternative workflows that use --no-ff. Maybe something interesting
will come of it.
-Peff
^ permalink raw reply
* git-svn and branches
From: Steven Walter @ 2007-09-27 2:12 UTC (permalink / raw)
To: git; +Cc: normalperson
I'm using git-svn to track a rather large subversion repository with a
non-standard layout. In the past, I've only cared about trunk, but now
I need to occasionally use branches, too. By adding a second git-svn
remote with the branch URL, I can fetch the branch, and git-svn is even
intelligent enough to notice that the branch was copied off of trunk.
However, git-svn also does a complete checkout for the first revision of
the branch. By this, I mean it goes through shows "A file" for every
file in the repository. This takes quite a while, and seems rather
unnecessary given that git-svn already noticed that the branch shares a
history with trunk, which is already fetched.
Knowing just enough of what git-svn is doing to be dangerous, I whipped
up a short little patch. This patch seems to work for the common case,
and avoids fetching every file from subversion. It does break
sometimes, however, and I don't understand why.
Maybe someone with a better grasps of the code can see what I did wrong,
or suggest a better means to my end?
diff --git a/git-svn.perl b/git-svn.perl
index 484b057..1bc92b6 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1848,9 +1848,10 @@ sub find_parent_branch {
$self->full_url, $ed)
or die "SVN connection failed somewhere...\n";
} else {
+ $self->assert_index_clean($parent);
print STDERR "Following parent with do_update\n";
$ed = SVN::Git::Fetcher->new($self);
- $self->ra->gs_do_update($rev, $rev, $self, $ed)
+ $self->ra->gs_do_update($rev, $r0, $self, $ed)
or die "SVN connection failed somewhere...\n";
}
print STDERR "Successfully followed parent\n";
--
-Steven Walter <stevenrwalter@gmail.com>
"A human being should be able to change a diaper, plan an invasion,
butcher a hog, conn a ship, design a building, write a sonnet, balance
accounts, build a wall, set a bone, comfort the dying, take orders,
give orders, cooperate, act alone, solve equations, analyze a new
problem, pitch manure, program a computer, cook a tasty meal, fight
efficiently, die gallantly. Specialization is for insects."
-Robert Heinlein
^ permalink raw reply related
* [PATCH] git-bundle: fix commandline examples in the manpage
From: Miklos Vajna @ 2007-09-26 23:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Miklos Vajna
Multiple commands were displayed in one line, making the manpage hard to read.
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
Documentation/git-bundle.txt | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 5051e2b..0cc6511 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -103,14 +103,20 @@ We set a tag in R1 (lastR2bundle) after the previous such transport,
and move it afterwards to help build the bundle.
in R1 on A:
+
+------------
$ git-bundle create mybundle master ^lastR2bundle
$ git tag -f lastR2bundle master
+------------
(move mybundle from A to B by some mechanism)
in R2 on B:
+
+------------
$ git-bundle verify mybundle
$ git-fetch mybundle refspec
+------------
where refspec is refInBundle:localRef
@@ -124,9 +130,11 @@ Also, with something like this in your config:
You can first sneakernet the bundle file to ~/tmp/file.bdl and
then these commands:
+------------
$ git ls-remote bundle
$ git fetch bundle
$ git pull bundle
+------------
would treat it as if it is talking with a remote side over the
network.
--
1.5.3.2.80.g077d6f-dirty
^ permalink raw reply related
* Re: [PATCH] Add --no-rename to git-apply
From: Robin Rosenberg @ 2007-09-26 22:31 UTC (permalink / raw)
To: junkio; +Cc: git
In-Reply-To: <11908420041596-git-send-email-robin.rosenberg@dewire.com>
onsdag 26 september 2007 skrev Robin Rosenberg:
> With this option git-apply can apply a patch with a rename
> onto the original file(s).
The reason (off the record) is that I use it for exporting to another
more expen$ive SCM, that does rename tracking so I need to keep
the file with the original name until telling the other SCM to rename
the file. It may be useful for others doing similar things.
-- robin
^ permalink raw reply
* [EGIT] UTF-8 in author names in history views read as ISO-8859-1
From: José Fonseca @ 2007-09-26 22:04 UTC (permalink / raw)
To: git
Hi,
First, thanks for the work on egit -- it is progressively becoming more
and more useful.
I found that spite UTF-8 being the default encoding, egit is interpreting
(or displaying) names as ISO-8859-1 in the history view.
BTW, something I really miss from egit is "Team > Compare With > HEAD
revision" or something like that.
Keep up the good work!
Cheers,
José Fonseca
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: Tom Clarke @ 2007-09-26 21:53 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0709262159430.28395@racer.site>
On 9/26/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Together with a resubmitted git-merge-rebase.sh (hint, hint), the
> mergeOptions would be quite useful for a workflow where you want to rebase
> on top of an upstream quite often.
I'll resubmit merge rebase tomorrow :-)
-Tom
^ permalink raw reply
* Re: What's cooking in git.git (topics)
From: Johannes Schindelin @ 2007-09-26 21:44 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfy11yyxk.fsf@gitster.siamese.dyndns.org>
Hi,
On Wed, 26 Sep 2007, Junio C Hamano wrote:
> * mv/unknown (Tue Sep 25 16:38:46 2007 +0200) 1 commit
> + Don't use "<unknown>" for placeholders and suppress printing of
> empty user formats.
>
> Parked in 'next'; I was already burned by it not passing one of the test
> cases, and I am not absolutely certain what else this subtly breaks.
> Hopefully minor.
I guess a few scripts could maybe rely on this behaviour. We should
advertise it as such.
> * lh/merge (Mon Sep 24 00:51:45 2007 +0200) 6 commits
> + git-merge: add --ff and --no-ff options
> + git-merge: add support for --commit and --no-squash
> + git-merge: add support for branch.<name>.mergeoptions
> + git-merge: refactor option parsing
> + git-merge: fix faulty SQUASH_MSG
> + Add test-script for git-merge porcelain
>
> Comments? I personally never felt need for --no-ff but the series is
> reasonably clean so I do not see strong objection against this series
> either.
Together with a resubmitted git-merge-rebase.sh (hint, hint), the
mergeOptions would be quite useful for a workflow where you want to rebase
on top of an upstream quite often.
> * js/rebase-i (Tue Sep 25 16:43:15 2007 +0100) 1 commit
> + rebase -i: work on a detached HEAD
>
> Waiting for autogc change as this textually interacts with it, and the
> additional convenience can wait.
Sure. I never used it anyway, but you specifically requested it ;-) BTW
thanks for merging the rest; especially the progress meter was a sore
point for me since long.
> * jc/autogc (Mon Sep 17 00:55:13 2007 -0700) 10 commits
> + git-gc --auto: run "repack -A -d -l" as necessary.
> + git-gc --auto: restructure the way "repack" command line is built.
> + git-gc --auto: protect ourselves from accumulated cruft
> + git-gc --auto: add documentation.
> + git-gc --auto: move threshold check to need_to_gc() function.
> + repack -A -d: use --keep-unreachable when repacking
> + pack-objects --keep-unreachable
> + Export matches_pack_name() and fix its return value
> + Invoke "git gc --auto" from commit, merge, am and rebase.
> + Implement git gc --auto
>
> I think the only remaining thing left with this thing is to prevent more
> than one instances of it from running at the same time. Any takers?
You mean, just creating a throw-away lock file?
> * ph/strbuf (Tue Sep 25 10:22:44 2007 +0200) 37 commits
> + Small cache_tree_write refactor.
> + Make builtin-rerere use of strbuf nicer and more efficient.
> + Add strbuf_cmp.
> + strbuf_setlen(): do not barf on setting length of an empty buffer
> to 0
> + sq_quote_argv and add_to_string rework with strbuf's.
> + Full rework of quote_c_style and write_name_quoted.
> + ...
>
> I had to make a small fix-up to strbuf_setlen() last night to this
> series; this should be ready for 'master'.
>
> And it is better to push this out early, as the series touches
> everywhere and conflicts with peoples' patches.
Hehe. Indeed, I had to fix the notes series after rebasing it...
> * db/fetch-pack (Tue Sep 25 00:13:25 2007 -0400) 45 commits
> + Prevent send-pack from segfaulting when a branch doesn't match
> + Cleanup unnecessary break in remote.c
> + Cleanup style nit of 'x == NULL' in remote.c
> + Fix memory leaks when disconnecting transport instances
> + Ensure builtin-fetch honors {fetch,transfer}.unpackLimit
> + ...
>
> Two issues known to me are:
>
> - "rsync" transport is not supported yet;
I promised to do this, and so I will today.
> * jc/stash-create (Mon Jul 9 00:51:23 2007 -0700) 2 commits
> + rebase: allow starting from a dirty tree.
> + stash: implement "stash create"
>
> I think "stash create" is going in a good direction, but I do not think
> rebase should unstash unconditionally on the resulting work tree. A
> good compromise might be not to unstash if the user asked to switch
> branches first and to unstash if he didn't.
Sounds like a sensible change to me; maybe a little warning after the
rebase?
I have no idea if I come around to do the same for rebase--interactive any
time soon, though.
Ciao,
Dscho
^ permalink raw reply
* [PATCH] post-checkout hook, tests, and docs
From: Josh England @ 2007-09-26 21:31 UTC (permalink / raw)
To: git; +Cc: Josh England
Updated post-checkout hook to take a flag specifying whether the checkout is
a branch checkout or a file checkout (from the index).
Signed-off-by: Josh England <jjengla@sandia.gov>
---
Documentation/hooks.txt | 14 ++++++++
git-checkout.sh | 12 +++++++
t/t5403-post-checkout-hook.sh | 74 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 100 insertions(+), 0 deletions(-)
create mode 100755 t/t5403-post-checkout-hook.sh
diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt
index 58b9547..f110162 100644
--- a/Documentation/hooks.txt
+++ b/Documentation/hooks.txt
@@ -87,6 +87,20 @@ parameter, and is invoked after a commit is made.
This hook is meant primarily for notification, and cannot affect
the outcome of `git-commit`.
+post-checkout
+-----------
+
+This hook is invoked when a `git-checkout` is run after having updated the
+worktree. The hook is given three parameters: the ref of the previous HEAD,
+the ref of the new HEAD (which may or may not have changed), and a flag
+indicating whether the checkout was a branch checkout (changing branches,
+flag=1) or a file checkout (retrieving a file from the index, flag=0).
+This hook cannot affect the outcome of `git-checkout`.
+
+This hook can be used to perform repository validity checks, auto-display
+differences from the previous HEAD if different, or set working dir metadata
+properties.
+
post-merge
-----------
diff --git a/git-checkout.sh b/git-checkout.sh
index 17f4392..8993920 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -137,6 +137,13 @@ Did you intend to checkout '$@' which can not be resolved as commit?"
git ls-files --error-unmatch -- "$@" >/dev/null || exit
git ls-files -- "$@" |
git checkout-index -f -u --stdin
+
+ # Run a post-checkout hook -- the HEAD does not change so the
+ # current HEAD is passed in for both args
+ if test -x "$GIT_DIR"/hooks/post-checkout; then
+ "$GIT_DIR"/hooks/post-checkout $old $old 0
+ fi
+
exit $?
else
# Make sure we did not fall back on $arg^{tree} codepath
@@ -284,3 +291,8 @@ if [ "$?" -eq 0 ]; then
else
exit 1
fi
+
+# Run a post-checkout hook
+if test -x "$GIT_DIR"/hooks/post-checkout; then
+ "$GIT_DIR"/hooks/post-checkout $old $new 1
+fi
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
new file mode 100755
index 0000000..e656aa1
--- /dev/null
+++ b/t/t5403-post-checkout-hook.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Josh England
+#
+
+test_description='Test the post-checkout hook.'
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo Data for commit0. >a &&
+ echo Data for commit0. >b &&
+ git update-index --add a &&
+ git update-index --add b &&
+ tree0=$(git write-tree) &&
+ commit0=$(echo setup | git commit-tree $tree0) &&
+ git update-ref refs/heads/master $commit0 &&
+ git-clone ./. clone1 &&
+ git-clone ./. clone2 &&
+ GIT_DIR=clone2/.git git branch -a new2 &&
+ echo Data for commit1. >clone2/b &&
+ GIT_DIR=clone2/.git git add clone2/b &&
+ GIT_DIR=clone2/.git git commit -m new2
+'
+
+for clone in 1 2; do
+ cat >clone${clone}/.git/hooks/post-checkout <<'EOF'
+#!/bin/sh
+echo $@ > $GIT_DIR/post-checkout.args
+EOF
+ chmod u+x clone${clone}/.git/hooks/post-checkout
+done
+
+test_expect_success 'post-checkout runs as expected ' '
+ GIT_DIR=clone1/.git git checkout master &&
+ test -e clone1/.git/post-checkout.args
+'
+
+test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' '
+ old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
+ new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
+ flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
+ test $old = $new -a $flag == 1
+'
+
+test_expect_success 'post-checkout runs as expected ' '
+ GIT_DIR=clone1/.git git checkout master &&
+ test -e clone1/.git/post-checkout.args
+'
+
+test_expect_success 'post-checkout args are correct with git checkout -b ' '
+ GIT_DIR=clone1/.git git checkout -b new1 &&
+ old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
+ new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
+ flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
+ test $old = $new -a $flag == 1
+'
+
+test_expect_success 'post-checkout receives the right args with HEAD changed ' '
+ GIT_DIR=clone2/.git git checkout new2 &&
+ old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
+ new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
+ flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
+ test $old != $new -a $flag == 1
+'
+
+test_expect_success 'post-checkout receives the right args when not switching branches ' '
+ GIT_DIR=clone2/.git git checkout master b &&
+ old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
+ new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
+ flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
+ test $old == $new -a $flag == 0
+'
+
+test_done
--
1.5.3.2.90.g6069e-dirty
^ permalink raw reply related
* [PATCH] Add --no-rename to git-apply
From: Robin Rosenberg @ 2007-09-26 21:26 UTC (permalink / raw)
To: junkio; +Cc: git, Robin Rosenberg
With this option git-apply can apply a patch with a rename
onto the original file(s).
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
Documentation/git-apply.txt | 6 ++-
builtin-apply.c | 17 +++++++-
t/t4123-apply-renames-norename.sh | 85 +++++++++++++++++++++++++++++++++++++
3 files changed, 106 insertions(+), 2 deletions(-)
create mode 100755 t/t4123-apply-renames-norename.sh
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 4c7e3a2..b691c55 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index]
- [--apply] [--no-add] [--index-info] [-R | --reverse]
+ [--apply] [--no-add] [--no-rename] [--index-info] [-R | --reverse]
[--allow-binary-replacement | --binary] [--reject] [-z]
[-pNUM] [-CNUM] [--inaccurate-eof] [--cached]
[--whitespace=<nowarn|warn|error|error-all|strip>]
@@ -121,6 +121,10 @@ discouraged.
the result with this option, which would apply the
deletion part but not addition part.
+--no-rename::
+ When applying patches with renames, this patch applies
+ the patch to the original file.
+
--allow-binary-replacement, --binary::
Historically we did not allow binary patch applied
without an explicit permission from the user, and this
diff --git a/builtin-apply.c b/builtin-apply.c
index 25b1447..73134e8 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -41,11 +41,12 @@ static int apply_in_reverse;
static int apply_with_reject;
static int apply_verbosely;
static int no_add;
+static int no_rename;
static int show_index_info;
static int line_termination = '\n';
static unsigned long p_context = ULONG_MAX;
static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
+"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--no-rename] [--index-info] [--allow-binary-replacement] [--reverse [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|error|error-all|strip>] <patch>...";
static enum whitespace_eol {
nowarn_whitespace,
@@ -495,6 +496,8 @@ static int gitdiff_copydst(const char *line, struct patch *patch)
static int gitdiff_renamesrc(const char *line, struct patch *patch)
{
+ if (no_rename)
+ return 0;
patch->is_rename = 1;
patch->old_name = find_name(line, NULL, 0, 0);
return 0;
@@ -502,6 +505,8 @@ static int gitdiff_renamesrc(const char *line, struct patch *patch)
static int gitdiff_renamedst(const char *line, struct patch *patch)
{
+ if (no_rename)
+ return 0;
patch->is_rename = 1;
patch->new_name = find_name(line, NULL, 0, 0);
return 0;
@@ -2103,6 +2108,11 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
struct cache_entry *ce = NULL;
int ok_if_exists;
+ if (no_rename) {
+ new_name = old_name;
+ patch->new_name = old_name;
+ }
+
patch->rejected = 1; /* we will drop this after we succeed */
/*
@@ -2843,6 +2853,11 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
no_add = 1;
continue;
}
+ if (!strcmp(arg, "--no-rename")) {
+ no_rename = 1;
+ continue;
+ }
+
if (!strcmp(arg, "--stat")) {
apply = 0;
diffstat = 1;
diff --git a/t/t4123-apply-renames-norename.sh b/t/t4123-apply-renames-norename.sh
new file mode 100755
index 0000000..8c0d523
--- /dev/null
+++ b/t/t4123-apply-renames-norename.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Robin Rosenberg
+#
+
+test_description='git apply --no-rename.
+
+'
+
+. ./test-lib.sh
+
+# setup
+
+mkdir -p klibc/arch/x86_64/include/klibc
+
+cat >klibc/arch/x86_64/include/klibc/archsetjmp.h <<\EOF
+/*
+ * arch/x86_64/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+ unsigned long __rbx;
+ unsigned long __rsp;
+ unsigned long __rbp;
+ unsigned long __r12;
+ unsigned long __r13;
+ unsigned long __r14;
+ unsigned long __r15;
+ unsigned long __rip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* _SETJMP_H */
+EOF
+
+cat >patch <<\EOF
+diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/m32r/klibc/archsetjmp.h
+similarity index 66%
+rename from klibc/arch/x86_64/include/klibc/archsetjmp.h
+rename to include/arch/m32r/klibc/archsetjmp.h
+--- a/klibc/arch/x86_64/include/klibc/archsetjmp.h
++++ b/include/arch/m32r/klibc/archsetjmp.h
+@@ -1,21 +1,21 @@
+ /*
+- * arch/x86_64/include/klibc/archsetjmp.h
++ * arch/m32r/include/klibc/archsetjmp.h
+ */
+
+ #ifndef _KLIBC_ARCHSETJMP_H
+ #define _KLIBC_ARCHSETJMP_H
+
+ struct __jmp_buf {
+- unsigned long __rbx;
+- unsigned long __rsp;
+- unsigned long __rbp;
++ unsigned long __r8;
++ unsigned long __r9;
++ unsigned long __r10;
++ unsigned long __r11;
+ unsigned long __r12;
+ unsigned long __r13;
+ unsigned long __r14;
+ unsigned long __r15;
+- unsigned long __rip;
+ };
+
+ typedef struct __jmp_buf jmp_buf[1];
+
+-#endif /* _SETJMP_H */
++#endif /* _KLIBC_ARCHSETJMP_H */
+EOF
+
+find klibc -type f -print | xargs git update-index --add --
+
+test_expect_success 'apply rename patch, without doing rename' \
+'git apply --no-rename patch &&
+git diff --numstat >stat.diff &&
+test "$(cat stat.diff)" = "6 6 klibc/arch/x86_64/include/klibc/archsetjmp.h"
+'
+
+test_done
--
1.5.3.1.g80926
^ permalink raw reply related
* Re: What's cooking in git.git (topics)
From: Carlos Rica @ 2007-09-26 21:07 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0709150047030.28586@racer.site>
2007/9/15, Johannes Schindelin <Johannes.Schindelin@gmx.de>:
> On Fri, 14 Sep 2007, Junio C Hamano wrote:
>
> > * cr/reset (Fri Sep 14 01:19:30 2007 -0700) 5 commits
> > + Simplify cache API
> > + An additional test for "git-reset -- path"
> > + Make "git reset" a builtin.
> > + Move make_cache_entry() from merge-recursive.c into read-cache.c
> > + Add tests for documented features of "git reset".
> >
> > I found "git reset commit paths..." had problem in this series,
> > which was why jc/cachetree is merged into this topic to fix it.
> > Hopefully we can put this in 'master' soon, after giving it
> > another and final round of eyeballing.
>
> I think this is my bug. The initial reset-with-paths functionality in the
> builtin reset came out of my feather... Sorry!
I'm sorry for not being able to review that code, but now it was
a bit too hard for my current knowledge of the git's internals.
These days I'm very busy here and I cannot continue with that work,
but I will be soon in git to learn more. Please, be free to rework the
code of builtin-reset.c without waiting for me if anyone is interested
in get it done ASAP.
--
Carlos
^ permalink raw reply
* Re: grafts not appearing in manual pages
From: J. Bruce Fields @ 2007-09-26 21:01 UTC (permalink / raw)
To: Mike Hommey; +Cc: git
In-Reply-To: <20070926202441.GA31848@glandium.org>
On Wed, Sep 26, 2007 at 10:24:41PM +0200, Mike Hommey wrote:
> Hi,
>
> The only occurrence of grafts in the manual pages is in the
> git-filter-branch one. I somehow feel this is wrong not to see it
> described more "formally" in the manual pages.
>
> I wouldn't mind writing a small something, except I have no idea what
> would be the most appropriate place to talk about it... Does anyone have
> such an idea ?
It could go in Documentation/user-manual.txt, but I don't know where.
Maybe at the end of the git-concepts chapter? Patches welcomed. I
guess what's needed (and currently missing) is an overview explaining
what they're actually for, plus some basic setup instructions.
And/or maybe a section 5 manual page documenting the format of the
"grafts" file? Maybe that's overkill. There's a paragraph in
Documentation/repository-layout.txt. Maybe we need to make it easier to
find that file.
--b.
^ permalink raw reply
* Re: [PATCH] User Manual: document import-tars.perl
From: J. Bruce Fields @ 2007-09-26 20:37 UTC (permalink / raw)
To: Miklos Vajna; +Cc: Junio C Hamano, git, Johannes Schindelin
In-Reply-To: <20070926182204.GB14959@genesis.frugalware.org>
On Wed, Sep 26, 2007 at 08:22:04PM +0200, Miklos Vajna wrote:
> On Wed, Sep 26, 2007 at 02:14:51PM -0400, "J. Bruce Fields" <bfields@fieldses.org> wrote:
> > Neat-o, I'd missed (or forgotten about) import-tars.perl.
> >
> > But I'd prefer to keep this first explanation of how to initialize and
> > commit to a new project pretty streamlined, and I don't think this is
> > really necessary here. So let's save this up until we have enough
> > material for a separate chapter or section on interacting with other
> > scm's.
>
> okay, now it's saved by gmane :)
Also in my git tree--I took yours and Johannes' suggestions, put them in
a blender, and added a brief skeleton of a new chapter at:
git://linux-nfs.org/~bfields/git.git docwork-foreign-scms
--b.
^ permalink raw reply
* grafts not appearing in manual pages
From: Mike Hommey @ 2007-09-26 20:24 UTC (permalink / raw)
To: git
Hi,
The only occurrence of grafts in the manual pages is in the
git-filter-branch one. I somehow feel this is wrong not to see it
described more "formally" in the manual pages.
I wouldn't mind writing a small something, except I have no idea what
would be the most appropriate place to talk about it... Does anyone have
such an idea ?
Cheers,
Mike
^ permalink raw reply
* What's cooking in git.git (topics)
From: Junio C Hamano @ 2007-09-26 20:05 UTC (permalink / raw)
To: git
In-Reply-To: <7v1wd1d0le.fsf@gitster.siamese.dyndns.org>
Here are the topics that have been cooking. Commits prefixed
with '-' are only in 'pu' while commits prefixed with '+' are
in 'next'. The topics list the commits in reverse chronological
order.
* jk/diff-rename (Tue Sep 25 15:29:42 2007 -0400) 1 commit
+ diffcore-rename: cache file deltas
Parked in 'next' for now but is 'master' material.
* mv/unknown (Tue Sep 25 16:38:46 2007 +0200) 1 commit
+ Don't use "<unknown>" for placeholders and suppress printing of
empty user formats.
Parked in 'next'; I was already burned by it not passing one of
the test cases, and I am not absolutely certain what else this
subtly breaks. Hopefully minor.
* jb/remote-rm (Sun Sep 23 22:29:12 2007 -0700) 3 commits
+ git-remote rm: add tests and minor fix-ups
+ remote: document the 'rm' subcommand
+ remote: add 'rm' subcommand
Should be Ok to push out to 'master'.
* ml/submodule (Sun Sep 23 22:19:42 2007 -0400) 1 commit
+ git-submodule - allow a relative path as the subproject url
Should be Ok to push out to 'master'.
* lh/merge (Mon Sep 24 00:51:45 2007 +0200) 6 commits
+ git-merge: add --ff and --no-ff options
+ git-merge: add support for --commit and --no-squash
+ git-merge: add support for branch.<name>.mergeoptions
+ git-merge: refactor option parsing
+ git-merge: fix faulty SQUASH_MSG
+ Add test-script for git-merge porcelain
Comments? I personally never felt need for --no-ff but the
series is reasonably clean so I do not see strong objection
against this series either.
* sv/svn (Fri Sep 21 15:27:01 2007 +1200) 3 commits
+ git-svn: handle changed svn command-line syntax
+ git-svn: fix test for trunk svn (transaction out of date)
+ git-svn: fix test for trunk svn (commit message not needed)
Will merge to 'master' this weekend.
* js/rebase-i (Tue Sep 25 16:43:15 2007 +0100) 1 commit
+ rebase -i: work on a detached HEAD
Waiting for autogc change as this textually interacts with it,
and the additional convenience can wait.
* jc/autogc (Mon Sep 17 00:55:13 2007 -0700) 10 commits
+ git-gc --auto: run "repack -A -d -l" as necessary.
+ git-gc --auto: restructure the way "repack" command line is built.
+ git-gc --auto: protect ourselves from accumulated cruft
+ git-gc --auto: add documentation.
+ git-gc --auto: move threshold check to need_to_gc() function.
+ repack -A -d: use --keep-unreachable when repacking
+ pack-objects --keep-unreachable
+ Export matches_pack_name() and fix its return value
+ Invoke "git gc --auto" from commit, merge, am and rebase.
+ Implement git gc --auto
I think the only remaining thing left with this thing is to
prevent more than one instances of it from running at the same
time. Any takers?
* ph/strbuf (Tue Sep 25 10:22:44 2007 +0200) 37 commits
+ Small cache_tree_write refactor.
+ Make builtin-rerere use of strbuf nicer and more efficient.
+ Add strbuf_cmp.
+ strbuf_setlen(): do not barf on setting length of an empty buffer
to 0
+ sq_quote_argv and add_to_string rework with strbuf's.
+ Full rework of quote_c_style and write_name_quoted.
+ ...
I had to make a small fix-up to strbuf_setlen() last night to
this series; this should be ready for 'master'.
And it is better to push this out early, as the series touches
everywhere and conflicts with peoples' patches.
* db/fetch-pack (Tue Sep 25 00:13:25 2007 -0400) 45 commits
+ Prevent send-pack from segfaulting when a branch doesn't match
+ Cleanup unnecessary break in remote.c
+ Cleanup style nit of 'x == NULL' in remote.c
+ Fix memory leaks when disconnecting transport instances
+ Ensure builtin-fetch honors {fetch,transfer}.unpackLimit
+ ...
Two issues known to me are:
- "rsync" transport is not supported yet;
- regresses "git pull <name>" using .git/remotes/<name>; does
not merge the first refspec when branch.<name>.merge is not
set.
There may be others but some people apparently use this in
production (including me) and I do not expect major breakages in
the really essential part.
* ss/svnimport (Mon Sep 24 12:57:40 2007 +0200) 1 commit
+ Fix pool handling in git-svnimport to avoid memory leaks.
This is meant to eventually go to 'maint' as well but with
diminishing user base of svnimport it is getting harder to get
good "tested successfully, seen improvements" reports.
* jc/stash-create (Mon Jul 9 00:51:23 2007 -0700) 2 commits
+ rebase: allow starting from a dirty tree.
+ stash: implement "stash create"
I think "stash create" is going in a good direction, but I do
not think rebase should unstash unconditionally on the resulting
work tree. A good compromise might be not to unstash if the
user asked to switch branches first and to unstash if he didn't.
* kh/commit (Mon Sep 17 20:06:48 2007 -0400) 7 commits
- Implement git commit as a builtin command.
- Export rerere() and launch_editor().
- Add strbuf_read_file().
- Clean up stripspace a bit, use strbuf even more.
- Introduce entry point for launching add--interactive.
- Enable wt-status to run against non-standard index file.
- Enable wt-status output to a given FILE pointer.
There were a few updates/replacements to the list I missed;
* gr/smtp (Tue Sep 25 17:27:54 2007 -0700) 2 commits
- [TO BE SQUASHED] Fix-up after review
- Add ability to specify SMTP server port when using git-send-email.
Will be in 'next'.
^ permalink raw reply
* What's in git.git (stable)
From: Junio C Hamano @ 2007-09-26 20:05 UTC (permalink / raw)
To: git
In-Reply-To: <7v3axhd0lr.fsf@gitster.siamese.dyndns.org>
Nothing earth-shattering in 'maint', except:
- if you are on FreeBSD and use its default shell, git scripts
might work better for you;
- comes with updated user-manual;
- send-email would not incorrectly issue duplicated message IDs
even if you fire many messages within one second;
- "git rm this-file && git commit this-file" should work
better;
----------------------------------------------------------------
* The 'maint' branch has these fixes since the last announcement.
Benoit Sigoure (1):
Add test to check recent fix to "git add -u"
David Brown (1):
Detect exec bit in more cases.
David Kastrup (1):
Supplant the "while case ... break ;; esac" idiom
Eric Wong (2):
Documentation/git-svn: updated design philosophy notes
git-svn: don't attempt to spawn pager if we don't want one
Gerrit Pape (1):
git-gui: lib/index.tcl: handle files with % in the filename
properly
Glenn Rempe (1):
Fixed minor typo in t/t9001-send-email.sh test command line.
J. Bruce Fields (14):
user-manual: adjust section levels in "git internals"
user-manual: move object format details to hacking-git chapter
user-manual: rename "git internals" to "git concepts"
user-manual: create new "low-level git operations" chapter
user-manual: rewrite index discussion
user-manual: reorder commit, blob, tree discussion
user-manual: rewrite object database discussion
user-manual: move packfile and dangling object discussion
user-manual: fix introduction to packfiles
user-manual: todo updates and cleanup
documentation: replace Discussion section by link to user-manual
chapter
core-tutorial: minor cleanup
git-apply: fix whitespace stripping
user-manual: don't assume refs are stored under .git/refs
Jakub Narebski (2):
gitweb: Remove parse_from_to_diffinfo code from git_patchset_body
gitweb: No difftree output for trivial merge
Jari Aalto (1):
Documentation/git-archive.txt: a couple of clarifications.
Jeff King (1):
git-push: documentation and tests for pushing only branches
Jim Meyering (2):
unexpected Make output (e.g. from --debug) causes build failure
Do not over-quote the -f envelopesender value.
Johannes Schindelin (2):
revision walker: --cherry-pick is a limited operation
apply --index-info: fall back to current index for mode changes
Johannes Sixt (2):
gitattributes.txt: Remove a duplicated paragraph about 'ident' and
'crlf' interaction.
gitattributes.txt: Be more to the point in the filter driver
description.
Junio C Hamano (11):
diff --no-index: do not forget to run diff_setup_done()
Documentation/git-config.txt: AsciiDoc tweak to avoid leading dot
Split grep arguments in a way that does not requires to add
/dev/null.
git-sh-setup: typofix in comments
send-email: make message-id generation a bit more robust
git-commit: Allow partial commit of file removal.
git-commit: partial commit of paths only removed from the index
Document ls-files --with-tree=<tree-ish>
t/t4014: test "am -3" with mode-only change.
GIT 1.5.3.2
Documentation/git-lost-found.txt: drop unnecessarily duplicated
name.
Linus Torvalds (1):
Fix the rename detection limit checking
Matt Kraai (2):
Move the paragraph specifying where the .idx and .pack files should
be
Conjugate "search" correctly in the git-prune-packed man page.
Matthias Urlichs (1):
git-svnimport: Use separate arguments in the pipe for git-rev-parse
Michael Smith (1):
user-manual: Explain what submodules are good for.
Michele Ballabio (2):
git-gui: show unstaged symlinks in diff viewer
git-gui: handle "deleted symlink" diff marker
Miklos Vajna (1):
User Manual: add a chapter for submodules
Pierre Habouzit (1):
Fix lapsus in builtin-apply.c
Randy Dunlap (1):
core-tutorial: correct URL
Shawn Bohrer (1):
Fix spelling of overridden in documentation
Shawn O. Pearce (13):
git-gui: Correct starting of git-remote to handle -w option
git-gui: Fix detaching current branch during checkout
git-gui: Properly set the state of "Stage/Unstage Hunk" action
git-gui: Disable Tk send in all git-gui sessions
git-gui: Avoid use of libdir in Makefile
git-gui: Assume untracked directories are Git submodules
git-gui: Trim trailing slashes from untracked submodule names
git-gui: Don't delete send on Windows as it doesn't exist
git-gui: Make backporting changes from i18n version easier
git-gui: Font chooser to handle a large number of font families
git-gui: Provide 'uninstall' Makefile target to undo an
installation
git-gui: Paper bag fix "Commit->Revert" format arguments
git-gui: Disable native platform text selection in "lists"
Väinö Järvelä (1):
Fixed update-hook example allow-users format.
* The 'master' branch has these since the last announcement
in addition to the above.
Carlos Rica (3):
Add tests for documented features of "git reset".
Move make_cache_entry() from merge-recursive.c into read-cache.c
Make "git reset" a builtin.
Christian Couder (4):
rev-list --bisect: Move finding bisection into do_find_bisection.
rev-list --bisect: Move some bisection code into best_bisection.
rev-list --bisect: Bisection "distance" clean up.
rev-list --bisect: Fix best == NULL case.
David Kastrup (3):
diff-delta.c: pack the index structure
diff-delta.c: Rationalize culling of hash buckets
git-commit.sh: Shell script cleanup
Dmitry Potapov (1):
preserve executable bits in zip archives
Jeff King (1):
contrib/fast-import: add perl version of simple example
Johannes Schindelin (7):
Teach "git remote" a mirror mode
verify-tag: also grok CR/LFs in the tag signature
apply: get rid of --index-info in favor of --build-fake-ancestor
rebase -i: commit when continuing after "edit"
rebase -i: style fixes and minor cleanups
rebase -i: Fix numbers in progress report
rebase -i: avoid exporting GIT_AUTHOR_* variables
Josh England (2):
Add post-merge hook, related documentation, and tests.
Added example hook script to save/restore permissions/ownership.
Junio C Hamano (8):
Keep last used delta base in the delta window
git-commit: Allow partial commit of file removal.
An additional test for "git-reset -- path"
Simplify cache API
git-commit: partial commit of paths only removed from the index
Document ls-files --with-tree=<tree-ish>
builtin-pack-objects.c: avoid bogus gcc warnings
Start RelNotes for 1.5.4
Lars Hjemli (3):
git-svn: add support for --first-parent
git-svn: always use --first-parent
Make merge-recursive honor diff.renamelimit
Matt Kraai (2):
Move convert-objects to contrib.
rebase -i: create .dotest-merge after validating options.
Nguyễn Thái Ngọc Duy (1):
contrib/fast-import: add simple shell example
Nicolas Pitre (10):
straighten the list of objects to deltify
localize window memory usage accounting
rearrange delta search progress reporting
basic threaded delta search
threaded delta search: refine work allocation
threaded delta search: better chunck split point
threaded delta search: specify number of threads at run time
fix threaded delta search locking
threaded delta search: add pack.threads config variable
threaded delta search: proper locking for cache accounting
^ permalink raw reply
* Re: [PATCH] User Manual: document import-tars.perl
From: Johannes Schindelin @ 2007-09-26 19:58 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: Miklos Vajna, Junio C Hamano, git
In-Reply-To: <20070926181451.GA20976@fieldses.org>
Hi,
On Wed, 26 Sep 2007, J. Bruce Fields wrote:
> On Wed, Sep 26, 2007 at 12:37:04AM +0200, Miklos Vajna wrote:
> > Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
> > ---
> >
> > On Tue, Sep 25, 2007 at 04:13:06PM -0400, "J. Bruce Fields" <bfields@fieldses.org> wrote:
> > > One exception--the "series of tarballs" thing--I think it's cool that
> > > you can just unpack a bunch of tarballs and string them together into a
> > > git history. It gives a good sense of how git works, and I don't think
> > > it's documented explicitly anywhere. I think that might be kinda fun to
> > > write up. But I haven't tried.
> >
> > something like this?
>
> Neat-o, I'd missed (or forgotten about) import-tars.perl.
You should also mention
$ mkdir my-new-repo
$ cd my-new-repo
$ git init
$ for z in /blub/*.zip
do
rm -rf * 2> /dev/null &&
unzip "$z" &&
git add . &&
git commit -m "$z" ||
break
done
import-tars.pl is much faster than this, of course, when it comes to tars,
but it has no clue about other archive formats.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] git-commit --amend: respect grafted parents.
From: Johannes Schindelin @ 2007-09-26 19:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, Johannes Sixt, git
In-Reply-To: <7vd4w51csv.fsf@gitster.siamese.dyndns.org>
Hi,
On Wed, 26 Sep 2007, Junio C Hamano wrote:
> Johannes Sixt <j.sixt@viscovery.net> writes:
>
> > Johannes Schindelin schrieb:
> >> The reason why I insist on not putting this into --amend is that I
> >> think this is not really an amend, but actively a rewrite of the
> >> merge commit.
> >
> > You have a point here. I'm convinced. Scrap the patch.
>
> I am slow today. Since when --amend is not about "a rewrite of commit"?
Technically, you are right, of course. Commit objects are immutable. But
from a _porcelain_ view I maintain that "amending" is about changes _to_ a
commit. It is not about redefining the (a) parent.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] post-checkout hook, and related docs and tests
From: Josh England @ 2007-09-26 19:23 UTC (permalink / raw)
To: Dmitry Potapov; +Cc: Junio C Hamano, git
In-Reply-To: <20070926145229.GA15300@potapov>
On Wed, 2007-09-26 at 18:52 +0400, Dmitry Potapov wrote:
> On Mon, Sep 24, 2007 at 02:07:36PM -0700, Junio C Hamano wrote:
> > "Josh England" <jjengla@sandia.gov> writes:
> >
> > > ... Granted, the
> > > branch (and HEAD) does not change for this operation, but that shouldn't
> > > matter. It is somewhat in line with the principle of 'least-surprise':
> > > if the hook runs for 'git checkout otherbranch', but not 'git checkout
> > > otherbranch path.c', this could cause confusion and distress to the
> > > user. IMO, it is a 'checkout' so the post-checkout hook should run.
> > > Why is that so insane?
> >
> > Because I find it would be surprising if the following commands
> > behave differently:
> >
> > $ git cat-file blob otherbranch:path.c >path.c
> > $ git show otherbranch:path.c >path.c
> > $ git diff -R otherbranch path.c | git apply
> > $ git checkout otherbranch path.c
>
> Actually, they already act differently even without any hook.
> If path.c is a symbol link then 1 and 2 will give a different
> result than commands 3 and 4.
Moroever, with respect to permissions, the first 2 retain the
permissions of the file if it already exists in the worktree, whereas
the other variations actually recreate the file with a default umask and
wipe out existing permissions.
> On the other hand, while the difference in above commands
> understandable (in case 1 and 2, the shell creates path.c; and
> in 3 and 4, git creates it), I really dislike the idea of
> "checkout is magical." I believe that command 3 and 4 should
> always give the same result or Git is broken.
>
> Another reason, why I dislike the post-checkout hook is that it
> is prone to abuse like as not so smart user trying to put some
> content modification here.
Content modification is not among the intended uses for this hook. Any
and all hooks can be abused/misused in this way. I just want to give
the user a tool -- if he wants to hit himself in the face with it that's
his prerogative.
> Moreover, it appears to be excessive
> to me, because if you want to run something after git-checkout,
> you can write a simple shell script for that that first runs
> git-checkout with the given arguments and then run whatever you
> want. I don't see why we should modify Git for that.
The same could be said for pre-commit and other hooks. The whole
reason for the hook system is to provide a useful interface so that
users are *not* required to write their own wrapper scripts to get the
job done. In this case, providing the hook is by far the *more*
consistent way of doing things.
> Perhaps, it would be better to have a hook on modification,
> which is invoked every time when Git wants to try to change
> anything in the working directory. The hook could receives on
> the input something that looks like 'git-diff --name-status'
> output and can do any work on creation files, etc. It is much
> more flexible, because you can do additional stuff here like
> creating one directory in the path as a symbol link somewhere
> else or something like that. But what is much more important
> is that everything work _consistently_ and you get the same
> results whether you type:
> git diff -R otherbranch path.c | git apply
> or
> git checkout otherbranch path.c
>
> If you start with one "magical interface" then eventually you
> will end up with everything being so magical that no one can
> make sense of it. Please, stay consistent.
I don't know why you think this is so magical. git-checkout can run a
post-checkout hook, if enabled. Plain and simple. No magic here. As
for the universal 'worktree-updated' hook, I look forward to seeing a
sane implementation, but in the meantime post-merge and post-checkout
suit my needs just fine.
-JE
^ permalink raw reply
* Re: [PATCH] git-commit --amend: respect grafted parents.
From: Junio C Hamano @ 2007-09-26 18:50 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Johannes Schindelin, Johannes Sixt, gitster, git
In-Reply-To: <46FA6CD7.1020709@viscovery.net>
Johannes Sixt <j.sixt@viscovery.net> writes:
> Johannes Schindelin schrieb:
>> The reason why I insist on not putting this into --amend is that I
>> think this is not really an amend, but actively a rewrite of the
>> merge commit.
>
> You have a point here. I'm convinced. Scrap the patch.
I am slow today. Since when --amend is not about "a rewrite of
commit"?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox