summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/add.c236
-rw-r--r--builtin/blame.c13
-rw-r--r--builtin/branch.c36
-rw-r--r--builtin/cat-file.c71
-rw-r--r--builtin/checkout.c7
-rw-r--r--builtin/clone.c18
-rw-r--r--builtin/commit.c2
-rw-r--r--builtin/count-objects.c44
-rw-r--r--builtin/fast-export.c8
-rw-r--r--builtin/fmt-merge-msg.c18
-rw-r--r--builtin/log.c168
-rw-r--r--builtin/merge-tree.c32
-rw-r--r--builtin/receive-pack.c5
-rw-r--r--builtin/remote.c2
-rw-r--r--builtin/revert.c4
-rw-r--r--builtin/shortlog.c4
-rw-r--r--builtin/show-branch.c17
17 files changed, 413 insertions, 272 deletions
diff --git a/builtin/add.c b/builtin/add.c
index 06f365d129..f45d9d4865 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -26,8 +26,55 @@ static int take_worktree_changes;
struct update_callback_data {
int flags;
int add_errors;
+ const char *implicit_dot;
+ size_t implicit_dot_len;
+
+ /* only needed for 2.0 transition preparation */
+ int warn_add_would_remove;
};
+static const char *option_with_implicit_dot;
+static const char *short_option_with_implicit_dot;
+
+static void warn_pathless_add(void)
+{
+ static int shown;
+ assert(option_with_implicit_dot && short_option_with_implicit_dot);
+
+ if (shown)
+ return;
+ shown = 1;
+
+ /*
+ * To be consistent with "git add -p" and most Git
+ * commands, we should default to being tree-wide, but
+ * this is not the original behavior and can't be
+ * changed until users trained themselves not to type
+ * "git add -u" or "git add -A". For now, we warn and
+ * keep the old behavior. Later, the behavior can be changed
+ * to tree-wide, keeping the warning for a while, and
+ * eventually we can drop the warning.
+ */
+ warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
+ "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
+ "To add content for the whole tree, run:\n"
+ "\n"
+ " git add %s :/\n"
+ " (or git add %s :/)\n"
+ "\n"
+ "To restrict the command to the current directory, run:\n"
+ "\n"
+ " git add %s .\n"
+ " (or git add %s .)\n"
+ "\n"
+ "With the current Git version, the command is restricted to "
+ "the current directory.\n"
+ ""),
+ option_with_implicit_dot, short_option_with_implicit_dot,
+ option_with_implicit_dot, short_option_with_implicit_dot,
+ option_with_implicit_dot, short_option_with_implicit_dot);
+}
+
static int fix_unmerged_status(struct diff_filepair *p,
struct update_callback_data *data)
{
@@ -49,15 +96,49 @@ static int fix_unmerged_status(struct diff_filepair *p,
return DIFF_STATUS_MODIFIED;
}
+static const char *add_would_remove_warning = N_(
+ "You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+" ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n");
+
+static void warn_add_would_remove(const char *path)
+{
+ warning(_(add_would_remove_warning), path);
+}
+
static void update_callback(struct diff_queue_struct *q,
struct diff_options *opt, void *cbdata)
{
int i;
struct update_callback_data *data = cbdata;
+ const char *implicit_dot = data->implicit_dot;
+ size_t implicit_dot_len = data->implicit_dot_len;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
const char *path = p->one->path;
+ /*
+ * Check if "git add -A" or "git add -u" was run from a
+ * subdirectory with a modified file outside that directory,
+ * and warn if so.
+ *
+ * "git add -u" will behave like "git add -u :/" instead of
+ * "git add -u ." in the future. This warning prepares for
+ * that change.
+ */
+ if (implicit_dot &&
+ strncmp_icase(path, implicit_dot, implicit_dot_len)) {
+ warn_pathless_add();
+ continue;
+ }
switch (fix_unmerged_status(p, data)) {
default:
die(_("unexpected diff status %c"), p->status);
@@ -70,6 +151,10 @@ static void update_callback(struct diff_queue_struct *q,
}
break;
case DIFF_STATUS_DELETED:
+ if (data->warn_add_would_remove) {
+ warn_add_would_remove(path);
+ data->warn_add_would_remove = 0;
+ }
if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
break;
if (!(data->flags & ADD_CACHE_PRETEND))
@@ -81,24 +166,34 @@ static void update_callback(struct diff_queue_struct *q,
}
}
-int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
+static void update_files_in_cache(const char *prefix, const char **pathspec,
+ struct update_callback_data *data)
{
- struct update_callback_data data;
struct rev_info rev;
+
init_revisions(&rev, prefix);
setup_revisions(0, NULL, &rev, NULL);
init_pathspec(&rev.prune_data, pathspec);
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = update_callback;
- data.flags = flags;
- data.add_errors = 0;
- rev.diffopt.format_callback_data = &data;
+ rev.diffopt.format_callback_data = data;
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
+}
+
+int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
+{
+ struct update_callback_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.flags = flags;
+ update_files_in_cache(prefix, pathspec, &data);
return !!data.add_errors;
}
-static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
+#define WARN_IMPLICIT_DOT (1u << 0)
+static char *prune_directory(struct dir_struct *dir, const char **pathspec,
+ int prefix, unsigned flag)
{
char *seen;
int i, specs;
@@ -115,6 +210,16 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec, int
if (match_pathspec(pathspec, entry->name, entry->len,
prefix, seen))
*dst++ = entry;
+ else if (flag & WARN_IMPLICIT_DOT)
+ /*
+ * "git add -A" was run from a subdirectory with a
+ * new file outside that directory.
+ *
+ * "git add -A" will behave like "git add -A :/"
+ * instead of "git add -A ." in the future.
+ * Warn about the coming behavior change.
+ */
+ warn_pathless_add();
}
dir->nr = dst - dir->entries;
add_pathspec_matches_against_index(pathspec, seen, specs);
@@ -270,23 +375,38 @@ static struct lock_file lock_file;
static const char ignore_error[] =
N_("The following paths are ignored by one of your .gitignore files:\n");
-static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
-static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
+static int verbose, show_only, ignored_too, refresh_only;
+static int ignore_add_errors, intent_to_add, ignore_missing;
+
+#define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
+static int addremove = ADDREMOVE_DEFAULT;
+static int addremove_explicit = -1; /* unspecified */
+
+static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
+{
+ /* if we are told to ignore, we are not adding removals */
+ *(int *)opt->value = !unset ? 0 : 1;
+ return 0;
+}
static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only, N_("dry run")),
OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_GROUP(""),
- OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
- OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
- OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
+ OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
+ OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
+ OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
- OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
- OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
- OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
- OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
- OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
- OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
+ OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
+ OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
+ OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
+ { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
+ NULL /* takes no arguments */,
+ N_("ignore paths removed in the working tree (same as --no-all)"),
+ PARSE_OPT_NOARG, ignore_removal_cb },
+ OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
+ OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
+ OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
OPT_END(),
};
@@ -321,35 +441,6 @@ static int add_files(struct dir_struct *dir, int flags)
return exit_status;
}
-static void warn_pathless_add(const char *option_name, const char *short_name) {
- /*
- * To be consistent with "git add -p" and most Git
- * commands, we should default to being tree-wide, but
- * this is not the original behavior and can't be
- * changed until users trained themselves not to type
- * "git add -u" or "git add -A". For now, we warn and
- * keep the old behavior. Later, the behavior can be changed
- * to tree-wide, keeping the warning for a while, and
- * eventually we can drop the warning.
- */
- warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
- "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
- "To add content for the whole tree, run:\n"
- "\n"
- " git add %s :/\n"
- " (or git add %s :/)\n"
- "\n"
- "To restrict the command to the current directory, run:\n"
- "\n"
- " git add %s .\n"
- " (or git add %s .)\n"
- "\n"
- "With the current Git version, the command is restricted to the current directory."),
- option_name, short_name,
- option_name, short_name,
- option_name, short_name);
-}
-
int cmd_add(int argc, const char **argv, const char *prefix)
{
int exit_status = 0;
@@ -360,8 +451,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
int add_new_files;
int require_pathspec;
char *seen = NULL;
- const char *option_with_implicit_dot = NULL;
- const char *short_option_with_implicit_dot = NULL;
+ int implicit_dot = 0;
+ struct update_callback_data update_data;
git_config(add_config, NULL);
@@ -377,8 +468,29 @@ int cmd_add(int argc, const char **argv, const char *prefix)
argc--;
argv++;
+ if (0 <= addremove_explicit)
+ addremove = addremove_explicit;
+ else if (take_worktree_changes && ADDREMOVE_DEFAULT)
+ addremove = 0; /* "-u" was given but not "-A" */
+
if (addremove && take_worktree_changes)
die(_("-A and -u are mutually incompatible"));
+
+ /*
+ * Warn when "git add pathspec..." was given without "-u" or "-A"
+ * and pathspec... covers a removed path.
+ */
+ memset(&update_data, 0, sizeof(update_data));
+ if (!take_worktree_changes && addremove_explicit < 0)
+ update_data.warn_add_would_remove = 1;
+
+ if (!take_worktree_changes && addremove_explicit < 0 && argc)
+ /*
+ * Turn "git add pathspec..." to "git add -A pathspec..."
+ * in Git 2.0 but not yet
+ */
+ ; /* addremove = 1; */
+
if (!show_only && ignore_missing)
die(_("Option --ignore-missing can only be used together with --dry-run"));
if (addremove) {
@@ -391,11 +503,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
if (option_with_implicit_dot && !argc) {
static const char *here[2] = { ".", NULL };
- if (prefix)
- warn_pathless_add(option_with_implicit_dot,
- short_option_with_implicit_dot);
argc = 1;
argv = here;
+ implicit_dot = 1;
}
add_new_files = !take_worktree_changes && !refresh_only;
@@ -408,7 +518,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
(intent_to_add ? ADD_CACHE_INTENT : 0) |
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
(!(addremove || take_worktree_changes)
- ? ADD_CACHE_IGNORE_REMOVAL : 0));
+ ? ADD_CACHE_IGNORE_REMOVAL : 0)) |
+ (implicit_dot ? ADD_CACHE_IMPLICIT_DOT : 0);
if (require_pathspec && argc == 0) {
fprintf(stderr, _("Nothing specified, nothing added.\n"));
@@ -432,15 +543,18 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
/* This picks up the paths that are not tracked */
- baselen = fill_directory(&dir, pathspec);
+ baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
if (pathspec)
- seen = prune_directory(&dir, pathspec, baselen);
+ seen = prune_directory(&dir, pathspec, baselen,
+ implicit_dot ? WARN_IMPLICIT_DOT : 0);
}
if (refresh_only) {
refresh(verbose, pathspec);
goto finish;
}
+ if (implicit_dot && prefix)
+ refresh_cache(REFRESH_QUIET);
if (pathspec) {
int i;
@@ -464,8 +578,20 @@ int cmd_add(int argc, const char **argv, const char *prefix)
plug_bulk_checkin();
- exit_status |= add_files_to_cache(prefix, pathspec, flags);
+ if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
+ /*
+ * Check for modified files throughout the worktree so
+ * update_callback has a chance to warn about changes
+ * outside the cwd.
+ */
+ update_data.implicit_dot = prefix;
+ update_data.implicit_dot_len = strlen(prefix);
+ pathspec = NULL;
+ }
+ update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
+ update_files_in_cache(prefix, pathspec, &update_data);
+ exit_status |= !!update_data.add_errors;
if (add_new_files)
exit_status |= add_files(&dir, flags);
diff --git a/builtin/blame.c b/builtin/blame.c
index 86100e9662..57a487e052 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1375,10 +1375,15 @@ static void get_ac_line(const char *inbuf, const char *what,
maillen = ident.mail_end - ident.mail_begin;
mailbuf = ident.mail_begin;
- *time = strtoul(ident.date_begin, NULL, 10);
+ if (ident.date_begin && ident.date_end)
+ *time = strtoul(ident.date_begin, NULL, 10);
+ else
+ *time = 0;
- len = ident.tz_end - ident.tz_begin;
- strbuf_add(tz, ident.tz_begin, len);
+ if (ident.tz_begin && ident.tz_end)
+ strbuf_add(tz, ident.tz_begin, ident.tz_end - ident.tz_begin);
+ else
+ strbuf_addstr(tz, "(unknown)");
/*
* Now, convert both name and e-mail using mailmap
@@ -1425,7 +1430,7 @@ static void get_commit_info(struct commit *commit,
commit_info_init(ret);
encoding = get_log_output_encoding();
- message = logmsg_reencode(commit, encoding);
+ message = logmsg_reencode(commit, NULL, encoding);
get_ac_line(message, "\nauthor ",
&ret->author, &ret->author_mail,
&ret->author_time, &ret->author_tz);
diff --git a/builtin/branch.c b/builtin/branch.c
index 3f0fbc082a..083689063f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -41,13 +41,15 @@ static char branch_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RED, /* REMOTE */
GIT_COLOR_NORMAL, /* LOCAL */
GIT_COLOR_GREEN, /* CURRENT */
+ GIT_COLOR_BLUE, /* UPSTREAM */
};
enum color_branch {
BRANCH_COLOR_RESET = 0,
BRANCH_COLOR_PLAIN = 1,
BRANCH_COLOR_REMOTE = 2,
BRANCH_COLOR_LOCAL = 3,
- BRANCH_COLOR_CURRENT = 4
+ BRANCH_COLOR_CURRENT = 4,
+ BRANCH_COLOR_UPSTREAM = 5
};
static enum merge_filter {
@@ -72,6 +74,8 @@ static int parse_branch_color_slot(const char *var, int ofs)
return BRANCH_COLOR_LOCAL;
if (!strcasecmp(var+ofs, "current"))
return BRANCH_COLOR_CURRENT;
+ if (!strcasecmp(var+ofs, "upstream"))
+ return BRANCH_COLOR_UPSTREAM;
return -1;
}
@@ -418,36 +422,52 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
int ours, theirs;
char *ref = NULL;
struct branch *branch = branch_get(branch_name);
+ struct strbuf fancy = STRBUF_INIT;
if (!stat_tracking_info(branch, &ours, &theirs)) {
if (branch && branch->merge && branch->merge[0]->dst &&
- show_upstream_ref)
- strbuf_addf(stat, "[%s] ",
- shorten_unambiguous_ref(branch->merge[0]->dst, 0));
+ show_upstream_ref) {
+ ref = shorten_unambiguous_ref(branch->merge[0]->dst, 0);
+ if (want_color(branch_use_color))
+ strbuf_addf(stat, "[%s%s%s] ",
+ branch_get_color(BRANCH_COLOR_UPSTREAM),
+ ref, branch_get_color(BRANCH_COLOR_RESET));
+ else
+ strbuf_addf(stat, "[%s] ", ref);
+ }
return;
}
- if (show_upstream_ref)
+ if (show_upstream_ref) {
ref = shorten_unambiguous_ref(branch->merge[0]->dst, 0);
+ if (want_color(branch_use_color))
+ strbuf_addf(&fancy, "%s%s%s",
+ branch_get_color(BRANCH_COLOR_UPSTREAM),
+ ref, branch_get_color(BRANCH_COLOR_RESET));
+ else
+ strbuf_addstr(&fancy, ref);
+ }
+
if (!ours) {
if (ref)
- strbuf_addf(stat, _("[%s: behind %d]"), ref, theirs);
+ strbuf_addf(stat, _("[%s: behind %d]"), fancy.buf, theirs);
else
strbuf_addf(stat, _("[behind %d]"), theirs);
} else if (!theirs) {
if (ref)
- strbuf_addf(stat, _("[%s: ahead %d]"), ref, ours);
+ strbuf_addf(stat, _("[%s: ahead %d]"), fancy.buf, ours);
else
strbuf_addf(stat, _("[ahead %d]"), ours);
} else {
if (ref)
strbuf_addf(stat, _("[%s: ahead %d, behind %d]"),
- ref, ours, theirs);
+ fancy.buf, ours, theirs);
else
strbuf_addf(stat, _("[ahead %d, behind %d]"),
ours, theirs);
}
+ strbuf_release(&fancy);
strbuf_addch(stat, ' ');
free(ref);
}
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 40f87b4649..045cee7bce 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -16,73 +16,6 @@
#define BATCH 1
#define BATCH_CHECK 2
-static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long size)
-{
- /* the parser in tag.c is useless here. */
- const char *endp = buf + size;
- const char *cp = buf;
-
- while (cp < endp) {
- char c = *cp++;
- if (c != '\n')
- continue;
- if (7 <= endp - cp && !memcmp("tagger ", cp, 7)) {
- const char *tagger = cp;
-
- /* Found the tagger line. Copy out the contents
- * of the buffer so far.
- */
- write_or_die(1, buf, cp - buf);
-
- /*
- * Do something intelligent, like pretty-printing
- * the date.
- */
- while (cp < endp) {
- if (*cp++ == '\n') {
- /* tagger to cp is a line
- * that has ident and time.
- */
- const char *sp = tagger;
- char *ep;
- unsigned long date;
- long tz;
- while (sp < cp && *sp != '>')
- sp++;
- if (sp == cp) {
- /* give up */
- write_or_die(1, tagger,
- cp - tagger);
- break;
- }
- while (sp < cp &&
- !('0' <= *sp && *sp <= '9'))
- sp++;
- write_or_die(1, tagger, sp - tagger);
- date = strtoul(sp, &ep, 10);
- tz = strtol(ep, NULL, 10);
- sp = show_date(date, tz, 0);
- write_or_die(1, sp, strlen(sp));
- xwrite(1, "\n", 1);
- break;
- }
- }
- break;
- }
- if (cp < endp && *cp == '\n')
- /* end of header */
- break;
- }
- /* At this point, we have copied out the header up to the end of
- * the tagger line and cp points at one past \n. It could be the
- * next header line after the tagger line, or it could be another
- * \n that marks the end of the headers. We need to copy out the
- * remainder as is.
- */
- if (cp < endp)
- write_or_die(1, cp, endp - cp);
-}
-
static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
{
unsigned char sha1[20];
@@ -133,10 +66,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
buf = read_sha1_file(sha1, &type, &size);
if (!buf)
die("Cannot read object %s", obj_name);
- if (type == OBJ_TAG) {
- pprint_tag(sha1, buf, size);
- return 0;
- }
/* otherwise just spit out the data */
break;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index f8033f446e..81b4419da5 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -35,6 +35,7 @@ struct checkout_opts {
int force_detach;
int writeout_stage;
int overwrite_ignore;
+ int ignore_skipworktree;
const char *new_branch;
const char *new_branch_force;
@@ -278,6 +279,8 @@ static int checkout_paths(const struct checkout_opts *opts,
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
ce->ce_flags &= ~CE_MATCHED;
+ if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
+ continue;
if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
/*
* "git checkout tree-ish -- path", but this entry
@@ -729,7 +732,7 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs)
"If you want to keep them by creating a new branch, "
"this may be a good time\nto do so with:\n\n"
" git branch new_branch_name %s\n\n"),
- sha1_to_hex(commit->object.sha1));
+ find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
}
/*
@@ -1058,6 +1061,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
OPT_STRING(0, "conflict", &conflict_style, N_("style"),
N_("conflict style (merge or diff3)")),
OPT_BOOLEAN('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
+ OPT_BOOL(0, "ignore-skip-worktree-bits", &opts.ignore_skipworktree,
+ N_("do not limit pathspecs to sparse entries only")),
{ OPTION_BOOLEAN, 0, "guess", &dwim_new_local_branch, NULL,
N_("second guess 'git checkout no-such-branch'"),
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
diff --git a/builtin/clone.c b/builtin/clone.c
index f9c380eb6c..035ab64950 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -232,16 +232,26 @@ static void strip_trailing_slashes(char *dir)
static int add_one_reference(struct string_list_item *item, void *cb_data)
{
char *ref_git;
+ const char *repo;
struct strbuf alternate = STRBUF_INIT;
- /* Beware: real_path() and mkpath() return static buffer */
+ /* Beware: read_gitfile(), real_path() and mkpath() return static buffer */
ref_git = xstrdup(real_path(item->string));
- if (is_directory(mkpath("%s/.git/objects", ref_git))) {
+
+ repo = read_gitfile(ref_git);
+ if (!repo)
+ repo = read_gitfile(mkpath("%s/.git", ref_git));
+ if (repo) {
+ free(ref_git);
+ ref_git = xstrdup(repo);
+ }
+
+ if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) {
char *ref_git_git = mkpathdup("%s/.git", ref_git);
free(ref_git);
ref_git = ref_git_git;
} else if (!is_directory(mkpath("%s/objects", ref_git)))
- die(_("reference repository '%s' is not a local directory."),
+ die(_("reference repository '%s' is not a local repository."),
item->string);
strbuf_addf(&alternate, "%s/objects", ref_git);
@@ -377,7 +387,7 @@ static void clone_local(const char *src_repo, const char *dest_repo)
static const char *junk_work_tree;
static const char *junk_git_dir;
static pid_t junk_pid;
-enum {
+static enum {
JUNK_LEAVE_NONE,
JUNK_LEAVE_REPO,
JUNK_LEAVE_ALL
diff --git a/builtin/commit.c b/builtin/commit.c
index 46204375e7..d2f30d960a 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -955,7 +955,7 @@ static const char *read_commit_message(const char *name)
if (!commit)
die(_("could not lookup commit %s"), name);
out_enc = get_commit_output_encoding();
- return logmsg_reencode(commit, out_enc);
+ return logmsg_reencode(commit, NULL, out_enc);
}
static int parse_and_validate_options(int argc, const char *argv[],
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 3a01a8d085..a7f70cb858 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -79,13 +79,13 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
}
static char const * const count_objects_usage[] = {
- N_("git count-objects [-v]"),
+ N_("git count-objects [-v] [-H | --human-readable]"),
NULL
};
int cmd_count_objects(int argc, const char **argv, const char *prefix)
{
- int i, verbose = 0;
+ int i, verbose = 0, human_readable = 0;
const char *objdir = get_object_directory();
int len = strlen(objdir);
char *path = xmalloc(len + 50);
@@ -93,6 +93,8 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
off_t loose_size = 0;
struct option opts[] = {
OPT__VERBOSE(&verbose, N_("be verbose")),
+ OPT_BOOL('H', "human-readable", &human_readable,
+ N_("print sizes in human readable format")),
OPT_END(),
};
@@ -119,6 +121,9 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
struct packed_git *p;
unsigned long num_pack = 0;
off_t size_pack = 0;
+ struct strbuf loose_buf = STRBUF_INIT;
+ struct strbuf pack_buf = STRBUF_INIT;
+ struct strbuf garbage_buf = STRBUF_INIT;
if (!packed_git)
prepare_packed_git();
for (p = packed_git; p; p = p->next) {
@@ -130,17 +135,40 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
size_pack += p->pack_size + p->index_size;
num_pack++;
}
+
+ if (human_readable) {
+ strbuf_humanise_bytes(&loose_buf, loose_size);
+ strbuf_humanise_bytes(&pack_buf, size_pack);
+ strbuf_humanise_bytes(&garbage_buf, size_garbage);
+ } else {
+ strbuf_addf(&loose_buf, "%lu",
+ (unsigned long)(loose_size / 1024));
+ strbuf_addf(&pack_buf, "%lu",
+ (unsigned long)(size_pack / 1024));
+ strbuf_addf(&garbage_buf, "%lu",
+ (unsigned long)(size_garbage / 1024));
+ }
+
printf("count: %lu\n", loose);
- printf("size: %lu\n", (unsigned long) (loose_size / 1024));
+ printf("size: %s\n", loose_buf.buf);
printf("in-pack: %lu\n", packed);
printf("packs: %lu\n", num_pack);
- printf("size-pack: %lu\n", (unsigned long) (size_pack / 1024));
+ printf("size-pack: %s\n", pack_buf.buf);
printf("prune-packable: %lu\n", packed_loose);
printf("garbage: %lu\n", garbage);
- printf("size-garbage: %lu\n", (unsigned long) (size_garbage / 1024));
+ printf("size-garbage: %s\n", garbage_buf.buf);
+ strbuf_release(&loose_buf);
+ strbuf_release(&pack_buf);
+ strbuf_release(&garbage_buf);
+ } else {
+ struct strbuf buf = STRBUF_INIT;
+ if (human_readable)
+ strbuf_humanise_bytes(&buf, loose_size);
+ else
+ strbuf_addf(&buf, "%lu kilobytes",
+ (unsigned long)(loose_size / 1024));
+ printf("%lu objects, %s\n", loose, buf.buf);
+ strbuf_release(&buf);
}
- else
- printf("%lu objects, %lu kilobytes\n",
- loose, (unsigned long) (loose_size / 1024));
return 0;
}
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 725c0a7dca..d60d675f6f 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -24,7 +24,7 @@ static const char *fast_export_usage[] = {
};
static int progress;
-static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;
+static enum { ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = ABORT;
static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ERROR;
static int fake_missing_tagger;
static int use_done_feature;
@@ -40,6 +40,8 @@ static int parse_opt_signed_tag_mode(const struct option *opt,
signed_tag_mode = VERBATIM;
else if (!strcmp(arg, "warn"))
signed_tag_mode = WARN;
+ else if (!strcmp(arg, "warn-strip"))
+ signed_tag_mode = WARN_STRIP;
else if (!strcmp(arg, "strip"))
signed_tag_mode = STRIP;
else
@@ -428,6 +430,10 @@ static void handle_tag(const char *name, struct tag *tag)
/* fallthru */
case VERBATIM:
break;
+ case WARN_STRIP:
+ warning ("Stripping signature from tag %s",
+ sha1_to_hex(tag->object.sha1));
+ /* fallthru */
case STRIP:
message_size = signature + 1 - message;
break;
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 265a9253bf..1c04070869 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -287,10 +287,10 @@ static void credit_people(struct strbuf *out,
const char *me;
if (kind == 'a') {
- label = "\n# By ";
+ label = "By";
me = git_author_info(IDENT_NO_DATE);
} else {
- label = "\n# Via ";
+ label = "Via";
me = git_committer_info(IDENT_NO_DATE);
}
@@ -300,7 +300,7 @@ static void credit_people(struct strbuf *out,
(me = skip_prefix(me, them->items->string)) != NULL &&
skip_prefix(me, " <")))
return;
- strbuf_addstr(out, label);
+ strbuf_addf(out, "\n%c %s ", comment_line_char, label);
add_people_count(out, them);
}
@@ -503,14 +503,18 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
} else {
if (tag_number == 2) {
struct strbuf tagline = STRBUF_INIT;
- strbuf_addf(&tagline, "\n# %s\n",
- origins.items[first_tag].string);
+ strbuf_addch(&tagline, '\n');
+ strbuf_add_commented_lines(&tagline,
+ origins.items[first_tag].string,
+ strlen(origins.items[first_tag].string));
strbuf_insert(&tagbuf, 0, tagline.buf,
tagline.len);
strbuf_release(&tagline);
}
- strbuf_addf(&tagbuf, "\n# %s\n",
- origins.items[i].string);
+ strbuf_addch(&tagbuf, '\n');
+ strbuf_add_commented_lines(&tagbuf,
+ origins.items[i].string,
+ strlen(origins.items[i].string));
fmt_tag_signature(&tagbuf, &sig, buf, len);
}
strbuf_release(&sig);
diff --git a/builtin/log.c b/builtin/log.c
index 0f318107e5..6e56a50002 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -37,7 +37,7 @@ static const char *fmt_patch_subject_prefix = "PATCH";
static const char *fmt_pretty;
static const char * const builtin_log_usage[] = {
- N_("git log [<options>] [<since>..<until>] [[--] <path>...]\n")
+ N_("git log [<options>] [<revision range>] [[--] <path>...]\n")
N_(" or: git show [options] <object>..."),
NULL
};
@@ -100,9 +100,9 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
int quiet = 0, source = 0, mailmap = 0;
const struct option builtin_log_options[] = {
- OPT_BOOLEAN(0, "quiet", &quiet, N_("suppress diff output")),
- OPT_BOOLEAN(0, "source", &source, N_("show source")),
- OPT_BOOLEAN(0, "use-mailmap", &mailmap, N_("Use mail map file")),
+ OPT_BOOL(0, "quiet", &quiet, N_("suppress diff output")),
+ OPT_BOOL(0, "source", &source, N_("show source")),
+ OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
PARSE_OPT_OPTARG, decorate_callback},
OPT_END()
@@ -622,6 +622,14 @@ static void add_header(const char *value)
static int thread;
static int do_signoff;
static const char *signature = git_version_string;
+static int config_cover_letter;
+
+enum {
+ COVER_UNSET,
+ COVER_OFF,
+ COVER_ON,
+ COVER_AUTO
+};
static int git_format_config(const char *var, const char *value, void *cb)
{
@@ -683,6 +691,14 @@ static int git_format_config(const char *var, const char *value, void *cb)
}
if (!strcmp(var, "format.signature"))
return git_config_string(&signature, var, value);
+ if (!strcmp(var, "format.coverletter")) {
+ if (value && !strcasecmp(value, "auto")) {
+ config_cover_letter = COVER_AUTO;
+ return 0;
+ }
+ config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
+ return 0;
+ }
return git_log_config(var, value, cb);
}
@@ -794,9 +810,37 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
}
}
+static char *find_branch_name(struct rev_info *rev)
+{
+ int i, positive = -1;
+ unsigned char branch_sha1[20];
+ const unsigned char *tip_sha1;
+ const char *ref;
+ char *full_ref, *branch = NULL;
+
+ for (i = 0; i < rev->cmdline.nr; i++) {
+ if (rev->cmdline.rev[i].flags & UNINTERESTING)
+ continue;
+ if (positive < 0)
+ positive = i;
+ else
+ return NULL;
+ }
+ if (positive < 0)
+ return NULL;
+ ref = rev->cmdline.rev[positive].name;
+ tip_sha1 = rev->cmdline.rev[positive].item->sha1;
+ if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
+ !prefixcmp(full_ref, "refs/heads/") &&
+ !hashcmp(tip_sha1, branch_sha1))
+ branch = xstrdup(full_ref + strlen("refs/heads/"));
+ free(full_ref);
+ return branch;
+}
+
static void make_cover_letter(struct rev_info *rev, int use_stdout,
struct commit *origin,
- int nr, struct commit **list, struct commit *head,
+ int nr, struct commit **list,
const char *branch_name,
int quiet)
{
@@ -810,6 +854,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
struct diff_options opts;
int need_8bit_cte = 0;
struct pretty_print_context pp = {0};
+ struct commit *head = list[0];
if (rev->commit_format != CMIT_FMT_EMAIL)
die(_("Cover letter needs email format"));
@@ -827,6 +872,9 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
if (has_non_ascii(list[i]->buffer))
need_8bit_cte = 1;
+ if (!branch_name)
+ branch_name = find_branch_name(rev);
+
msg = body;
pp.fmt = CMIT_FMT_EMAIL;
pp.date_mode = DATE_RFC2822;
@@ -1033,45 +1081,6 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
return 0;
}
-static char *find_branch_name(struct rev_info *rev)
-{
- int i, positive = -1;
- unsigned char branch_sha1[20];
- const unsigned char *tip_sha1;
- const char *ref;
- char *full_ref, *branch = NULL;
-
- for (i = 0; i < rev->cmdline.nr; i++) {
- if (rev->cmdline.rev[i].flags & UNINTERESTING)
- continue;
- if (positive < 0)
- positive = i;
- else
- return NULL;
- }
- if (0 <= positive) {
- ref = rev->cmdline.rev[positive].name;
- tip_sha1 = rev->cmdline.rev[positive].item->sha1;
- } else if (!rev->cmdline.nr && rev->pending.nr == 1 &&
- !strcmp(rev->pending.objects[0].name, "HEAD")) {
- /*
- * No actual ref from command line, but "HEAD" from
- * rev->def was added in setup_revisions()
- * e.g. format-patch --cover-letter -12
- */
- ref = "HEAD";
- tip_sha1 = rev->pending.objects[0].item->sha1;
- } else {
- return NULL;
- }
- if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
- !prefixcmp(full_ref, "refs/heads/") &&
- !hashcmp(tip_sha1, branch_sha1))
- branch = xstrdup(full_ref + strlen("refs/heads/"));
- free(full_ref);
- return branch;
-}
-
int cmd_format_patch(int argc, const char **argv, const char *prefix)
{
struct commit *commit;
@@ -1083,10 +1092,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
int start_number = -1;
int just_numbers = 0;
int ignore_if_in_upstream = 0;
- int cover_letter = 0;
+ int cover_letter = -1;
int boundary_count = 0;
int no_binary_diff = 0;
- struct commit *origin = NULL, *head = NULL;
+ struct commit *origin = NULL;
const char *in_reply_to = NULL;
struct patch_ids ids;
struct strbuf buf = STRBUF_INIT;
@@ -1101,12 +1110,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
{ OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
N_("use [PATCH] even with multiple patches"),
PARSE_OPT_NOARG, no_numbered_callback },
- OPT_BOOLEAN('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
- OPT_BOOLEAN(0, "stdout", &use_stdout,
+ OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
+ OPT_BOOL(0, "stdout", &use_stdout,
N_("print patches to standard out")),
- OPT_BOOLEAN(0, "cover-letter", &cover_letter,
+ OPT_BOOL(0, "cover-letter", &cover_letter,
N_("generate a cover letter")),
- OPT_BOOLEAN(0, "numbered-files", &just_numbers,
+ OPT_BOOL(0, "numbered-files", &just_numbers,
N_("use simple number sequence for output file names")),
OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
N_("use <sfx> instead of '.patch'")),
@@ -1280,28 +1289,36 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
}
if (rev.pending.nr == 1) {
+ int check_head = 0;
+
if (rev.max_count < 0 && !rev.show_root_diff) {
/*
* This is traditional behaviour of "git format-patch
* origin" that prepares what the origin side still
* does not have.
*/
- unsigned char sha1[20];
- const char *ref;
-
rev.pending.objects[0].item->flags |= UNINTERESTING;
add_head_to_pending(&rev);
- ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
- if (ref && !prefixcmp(ref, "refs/heads/"))
- branch_name = xstrdup(ref + strlen("refs/heads/"));
- else
- branch_name = xstrdup(""); /* no branch */
+ check_head = 1;
}
/*
* Otherwise, it is "format-patch -22 HEAD", and/or
* "format-patch --root HEAD". The user wants
* get_revision() to do the usual traversal.
*/
+
+ if (!strcmp(rev.pending.objects[0].name, "HEAD"))
+ check_head = 1;
+
+ if (check_head) {
+ unsigned char sha1[20];
+ const char *ref;
+ ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
+ if (ref && !prefixcmp(ref, "refs/heads/"))
+ branch_name = xstrdup(ref + strlen("refs/heads/"));
+ else
+ branch_name = xstrdup(""); /* no branch */
+ }
}
/*
@@ -1310,29 +1327,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
*/
rev.show_root_diff = 1;
- if (cover_letter) {
- /*
- * NEEDSWORK:randomly pick one positive commit to show
- * diffstat; this is often the tip and the command
- * happens to do the right thing in most cases, but a
- * complex command like "--cover-letter a b c ^bottom"
- * picks "c" and shows diffstat between bottom..c
- * which may not match what the series represents at
- * all and totally broken.
- */
- int i;
- for (i = 0; i < rev.pending.nr; i++) {
- struct object *o = rev.pending.objects[i].item;
- if (!(o->flags & UNINTERESTING))
- head = (struct commit *)o;
- }
- /* There is nothing to show; it is not an error, though. */
- if (!head)
- return 0;
- if (!branch_name)
- branch_name = find_branch_name(&rev);
- }
-
if (ignore_if_in_upstream) {
/* Don't say anything if head and upstream are the same. */
if (rev.pending.nr == 2) {
@@ -1364,11 +1358,21 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
list = xrealloc(list, nr * sizeof(list[0]));
list[nr - 1] = commit;
}
+ if (nr == 0)
+ /* nothing to do */
+ return 0;
total = nr;
if (!keep_subject && auto_number && total > 1)
numbered = 1;
if (numbered)
rev.total = total + start_number - 1;
+ if (cover_letter == -1) {
+ if (config_cover_letter == COVER_AUTO)
+ cover_letter = (total > 1);
+ else
+ cover_letter = (config_cover_letter == COVER_ON);
+ }
+
if (in_reply_to || thread || cover_letter)
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
if (in_reply_to) {
@@ -1381,7 +1385,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (thread)
gen_message_id(&rev, "cover");
make_cover_letter(&rev, use_stdout,
- origin, nr, list, head, branch_name, quiet);
+ origin, nr, list, branch_name, quiet);
total++;
start_number--;
}
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index bc912e399e..61cbde4094 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -155,6 +155,11 @@ static int same_entry(struct name_entry *a, struct name_entry *b)
a->mode == b->mode;
}
+static int both_empty(struct name_entry *a, struct name_entry *b)
+{
+ return !(a->sha1 || b->sha1);
+}
+
static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsigned char *sha1, const char *path)
{
struct merge_list *res = xcalloc(1, sizeof(*res));
@@ -246,7 +251,11 @@ static void unresolved(const struct traverse_info *info, struct name_entry n[3])
for (i = 0; i < 3; i++) {
mask |= (1 << i);
- if (n[i].mode && S_ISDIR(n[i].mode))
+ /*
+ * Treat missing entries as directories so that we return
+ * after unresolved_directory has handled this.
+ */
+ if (!n[i].mode || S_ISDIR(n[i].mode))
dirmask |= (1 << i);
}
@@ -297,13 +306,10 @@ static void unresolved(const struct traverse_info *info, struct name_entry n[3])
static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *info)
{
/* Same in both? */
- if (same_entry(entry+1, entry+2)) {
- if (entry[0].sha1) {
- /* Modified identically */
- resolve(info, NULL, entry+1);
- return mask;
- }
- /* "Both added the same" is left unresolved */
+ if (same_entry(entry+1, entry+2) || both_empty(entry+1, entry+2)) {
+ /* Modified, added or removed identically */
+ resolve(info, NULL, entry+1);
+ return mask;
}
if (same_entry(entry+0, entry+1)) {
@@ -319,12 +325,10 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
*/
}
- if (same_entry(entry+0, entry+2)) {
- if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) {
- /* We modified, they did not touch -- take ours */
- resolve(info, NULL, entry+1);
- return mask;
- }
+ if (same_entry(entry+0, entry+2) || both_empty(entry+0, entry+2)) {
+ /* We added, modified or removed, they did not touch -- take ours */
+ resolve(info, NULL, entry+1);
+ return mask;
}
unresolved(info, entry);
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ccebd74f16..e3eb5fc058 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -826,8 +826,11 @@ static const char *unpack(int err_fd)
: 0);
hdr_err = parse_pack_header(&hdr);
- if (hdr_err)
+ if (hdr_err) {
+ if (err_fd > 0)
+ close(err_fd);
return hdr_err;
+ }
snprintf(hdr_arg, sizeof(hdr_arg),
"--pack_header=%"PRIu32",%"PRIu32,
ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
diff --git a/builtin/remote.c b/builtin/remote.c
index 937484d7c7..5e54d367b8 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -178,7 +178,7 @@ static int add(int argc, const char **argv)
argc = parse_options(argc, argv, NULL, options, builtin_remote_add_usage,
0);
- if (argc < 2)
+ if (argc != 2)
usage_with_options(builtin_remote_add_usage, options);
if (mirror && master)
diff --git a/builtin/revert.c b/builtin/revert.c
index c5e36b94c0..0401fdb02c 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -19,13 +19,13 @@
*/
static const char * const revert_usage[] = {
- N_("git revert [options] <commit-ish>"),
+ N_("git revert [options] <commit-ish>..."),
N_("git revert <subcommand>"),
NULL
};
static const char * const cherry_pick_usage[] = {
- N_("git cherry-pick [options] <commit-ish>"),
+ N_("git cherry-pick [options] <commit-ish>..."),
N_("git cherry-pick <subcommand>"),
NULL
};
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 240bff3efa..1fd6f8ac59 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -10,9 +10,7 @@
#include "parse-options.h"
static char const * const shortlog_usage[] = {
- N_("git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"),
- "",
- N_("[rev-opts] are documented in git-rev-list(1)"),
+ N_("git shortlog [<options>] [<revision range>] [[--] [<path>...]]"),
NULL
};
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d208fd6c68..90fc6b1b9d 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -162,29 +162,28 @@ static void name_commits(struct commit_list *list,
nth = 0;
while (parents) {
struct commit *p = parents->item;
- char newname[1000], *en;
+ struct strbuf newname = STRBUF_INIT;
parents = parents->next;
nth++;
if (p->util)
continue;
- en = newname;
switch (n->generation) {
case 0:
- en += sprintf(en, "%s", n->head_name);
+ strbuf_addstr(&newname, n->head_name);
break;
case 1:
- en += sprintf(en, "%s^", n->head_name);
+ strbuf_addf(&newname, "%s^", n->head_name);
break;
default:
- en += sprintf(en, "%s~%d",
- n->head_name, n->generation);
+ strbuf_addf(&newname, "%s~%d",
+ n->head_name, n->generation);
break;
}
if (nth == 1)
- en += sprintf(en, "^");
+ strbuf_addch(&newname, '^');
else
- en += sprintf(en, "^%d", nth);
- name_commit(p, xstrdup(newname), 0);
+ strbuf_addf(&newname, "^%d", nth);
+ name_commit(p, strbuf_detach(&newname, NULL), 0);
i++;
name_first_parent_chain(p);
}