зеркало из https://github.com/microsoft/git.git
Merge branch 'maint'
* maint: tutorial: gentler illustration of Alice/Bob workflow using gitk pretty=format: respect date format options make git-shell paranoid about closed stdin/stdout/stderr Document gitk --argscmd flag. Fix '--dirstat' with cross-directory renaming for-each-ref: Allow a trailing slash in the patterns
This commit is contained in:
Коммит
445cac18c0
|
@ -49,6 +49,13 @@ frequently used options.
|
|||
the history between two branches (i.e. the HEAD and the MERGE_HEAD)
|
||||
that modify the conflicted files.
|
||||
|
||||
--argscmd=<command>::
|
||||
Command to be run each time gitk has to determine the list of
|
||||
<revs> to show. The command is expected to print on its standard
|
||||
output a list of additional revs to be shown, one per line.
|
||||
Use this instead of explicitly specifying <revs> if the set of
|
||||
commits to show may vary between refreshes.
|
||||
|
||||
<revs>::
|
||||
|
||||
Limit the revisions to show. This can be either a single revision
|
||||
|
|
|
@ -321,10 +321,37 @@ pulling, like this:
|
|||
|
||||
------------------------------------------------
|
||||
alice$ git fetch /home/bob/myrepo master
|
||||
alice$ git log -p ..FETCH_HEAD
|
||||
alice$ git log -p HEAD..FETCH_HEAD
|
||||
------------------------------------------------
|
||||
|
||||
This operation is safe even if Alice has uncommitted local changes.
|
||||
The range notation HEAD..FETCH_HEAD" means "show everything that is reachable
|
||||
from the FETCH_HEAD but exclude anything that is reachable from HEAD.
|
||||
Alice already knows everything that leads to her current state (HEAD),
|
||||
and reviewing what Bob has in his state (FETCH_HEAD) that she has not
|
||||
seen with this command
|
||||
|
||||
If Alice wants to visualize what Bob did since their histories forked
|
||||
she can issue the following command:
|
||||
|
||||
------------------------------------------------
|
||||
$ gitk HEAD..FETCH_HEAD
|
||||
------------------------------------------------
|
||||
|
||||
This uses the same two-dot range notation we saw earlier with 'git log'.
|
||||
|
||||
Alice may want to view what both of them did since they forked.
|
||||
She can use three-dot form instead of the two-dot form:
|
||||
|
||||
------------------------------------------------
|
||||
$ gitk HEAD...FETCH_HEAD
|
||||
------------------------------------------------
|
||||
|
||||
This means "show everything that is reachable from either one, but
|
||||
exclude anything that is reachable from both of them".
|
||||
|
||||
Please note that these range notation can be used with both gitk
|
||||
and "git log".
|
||||
|
||||
After inspecting what Bob did, if there is nothing urgent, Alice may
|
||||
decide to continue working without pulling from Bob. If Bob's history
|
||||
|
|
|
@ -103,7 +103,7 @@ The placeholders are:
|
|||
- '%an': author name
|
||||
- '%aN': author name (respecting .mailmap)
|
||||
- '%ae': author email
|
||||
- '%ad': author date
|
||||
- '%ad': author date (format respects --date= option)
|
||||
- '%aD': author date, RFC2822 style
|
||||
- '%ar': author date, relative
|
||||
- '%at': author date, UNIX timestamp
|
||||
|
|
|
@ -48,7 +48,7 @@ static void format_subst(const struct commit *commit,
|
|||
strbuf_add(&fmt, b + 8, c - b - 8);
|
||||
|
||||
strbuf_add(buf, src, b - src);
|
||||
format_commit_message(commit, fmt.buf, buf);
|
||||
format_commit_message(commit, fmt.buf, buf, DATE_NORMAL);
|
||||
len -= c + 1 - src;
|
||||
src = c + 1;
|
||||
}
|
||||
|
|
|
@ -882,7 +882,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
|
|||
|
||||
if (!log_tree_commit(&rev, commit)) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
format_commit_message(commit, "%h: %s", &buf);
|
||||
format_commit_message(commit, "%h: %s", &buf, DATE_NORMAL);
|
||||
printf("%s\n", buf.buf);
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
|
|
@ -652,7 +652,8 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
|
|||
if ((plen <= namelen) &&
|
||||
!strncmp(refname, p, plen) &&
|
||||
(refname[plen] == '\0' ||
|
||||
refname[plen] == '/'))
|
||||
refname[plen] == '/' ||
|
||||
p[plen-1] == '/'))
|
||||
break;
|
||||
if (!fnmatch(p, refname, FNM_PATHNAME))
|
||||
break;
|
||||
|
|
3
commit.h
3
commit.h
|
@ -67,7 +67,8 @@ extern int non_ascii(int);
|
|||
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
|
||||
extern void get_commit_format(const char *arg, struct rev_info *);
|
||||
extern void format_commit_message(const struct commit *commit,
|
||||
const void *format, struct strbuf *sb);
|
||||
const void *format, struct strbuf *sb,
|
||||
enum date_mode dmode);
|
||||
extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
|
||||
struct strbuf *,
|
||||
int abbrev, const char *subject,
|
||||
|
|
8
diff.c
8
diff.c
|
@ -1060,6 +1060,13 @@ static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long ch
|
|||
return this_dir;
|
||||
}
|
||||
|
||||
static int dirstat_compare(const void *_a, const void *_b)
|
||||
{
|
||||
const struct dirstat_file *a = _a;
|
||||
const struct dirstat_file *b = _b;
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static void show_dirstat(struct diff_options *options)
|
||||
{
|
||||
int i;
|
||||
|
@ -1119,6 +1126,7 @@ static void show_dirstat(struct diff_options *options)
|
|||
return;
|
||||
|
||||
/* Show all directories with more than x% of the changes */
|
||||
qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
|
||||
gather_dirstat(options->file, &dir, changed, "", 0);
|
||||
}
|
||||
|
||||
|
|
17
pretty.c
17
pretty.c
|
@ -310,7 +310,7 @@ static int mailmap_name(struct strbuf *sb, const char *email)
|
|||
}
|
||||
|
||||
static size_t format_person_part(struct strbuf *sb, char part,
|
||||
const char *msg, int len)
|
||||
const char *msg, int len, enum date_mode dmode)
|
||||
{
|
||||
/* currently all placeholders have same length */
|
||||
const int placeholder_len = 2;
|
||||
|
@ -377,7 +377,7 @@ static size_t format_person_part(struct strbuf *sb, char part,
|
|||
|
||||
switch (part) {
|
||||
case 'd': /* date */
|
||||
strbuf_addstr(sb, show_date(date, tz, DATE_NORMAL));
|
||||
strbuf_addstr(sb, show_date(date, tz, dmode));
|
||||
return placeholder_len;
|
||||
case 'D': /* date, RFC2822 style */
|
||||
strbuf_addstr(sb, show_date(date, tz, DATE_RFC2822));
|
||||
|
@ -409,6 +409,7 @@ struct chunk {
|
|||
|
||||
struct format_commit_context {
|
||||
const struct commit *commit;
|
||||
enum date_mode dmode;
|
||||
|
||||
/* These offsets are relative to the start of the commit message. */
|
||||
int commit_header_parsed;
|
||||
|
@ -584,10 +585,12 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
|
|||
return 1;
|
||||
case 'a': /* author ... */
|
||||
return format_person_part(sb, placeholder[1],
|
||||
msg + c->author.off, c->author.len);
|
||||
msg + c->author.off, c->author.len,
|
||||
c->dmode);
|
||||
case 'c': /* committer ... */
|
||||
return format_person_part(sb, placeholder[1],
|
||||
msg + c->committer.off, c->committer.len);
|
||||
msg + c->committer.off, c->committer.len,
|
||||
c->dmode);
|
||||
case 'e': /* encoding */
|
||||
strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
|
||||
return 1;
|
||||
|
@ -599,12 +602,14 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
|
|||
}
|
||||
|
||||
void format_commit_message(const struct commit *commit,
|
||||
const void *format, struct strbuf *sb)
|
||||
const void *format, struct strbuf *sb,
|
||||
enum date_mode dmode)
|
||||
{
|
||||
struct format_commit_context context;
|
||||
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.commit = commit;
|
||||
context.dmode = dmode;
|
||||
strbuf_expand(sb, format, format_commit_item, &context);
|
||||
}
|
||||
|
||||
|
@ -770,7 +775,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
|
|||
const char *encoding;
|
||||
|
||||
if (fmt == CMIT_FMT_USERFORMAT) {
|
||||
format_commit_message(commit, user_format, sb);
|
||||
format_commit_message(commit, user_format, sb, dmode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
13
shell.c
13
shell.c
|
@ -48,6 +48,19 @@ int main(int argc, char **argv)
|
|||
{
|
||||
char *prog;
|
||||
struct commands *cmd;
|
||||
int devnull_fd;
|
||||
|
||||
/*
|
||||
* Always open file descriptors 0/1/2 to avoid clobbering files
|
||||
* in die(). It also avoids not messing up when the pipes are
|
||||
* dup'ed onto stdin/stdout/stderr in the child processes we spawn.
|
||||
*/
|
||||
devnull_fd = open("/dev/null", O_RDWR);
|
||||
while (devnull_fd >= 0 && devnull_fd <= 2)
|
||||
devnull_fd = dup(devnull_fd);
|
||||
if (devnull_fd == -1)
|
||||
die("opening /dev/null failed (%s)", strerror(errno));
|
||||
close (devnull_fd);
|
||||
|
||||
/*
|
||||
* Special hack to pretend to be a CVS server
|
||||
|
|
|
@ -139,6 +139,12 @@ commit 131a310eb913d107dd3c09a65d1651175898735d
|
|||
commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
|
||||
EOF
|
||||
|
||||
test_expect_success '%ad respects --date=' '
|
||||
echo 2005-04-07 >expect.ad-short &&
|
||||
git log -1 --date=short --pretty=tformat:%ad >output.ad-short master &&
|
||||
test_cmp expect.ad-short output.ad-short
|
||||
'
|
||||
|
||||
test_expect_success 'empty email' '
|
||||
test_tick &&
|
||||
C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче