зеркало из https://github.com/microsoft/git.git
Merge branch 'jc/combined'
* jc/combined: combine-diff: a few more finishing touches. Documentation: clarify refname disambiguation rules. diff-format.txt: Combined diff format documentation supplement Remove --syslog in git-daemon inetd documentation examples. Documentation: updates to "Everyday GIT"
This commit is contained in:
Коммит
e893f7ad73
|
@ -156,31 +156,91 @@ to produce 'combined diff', which looks like this:
|
||||||
|
|
||||||
------------
|
------------
|
||||||
diff --combined describe.c
|
diff --combined describe.c
|
||||||
@@@ +98,7 @@@
|
index fabadb8,cc95eb0..4866510
|
||||||
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
|
--- a/describe.c
|
||||||
|
+++ b/describe.c
|
||||||
|
@@@ -98,20 -98,12 +98,20 @@@
|
||||||
|
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
- static void describe(char *arg)
|
- static void describe(char *arg)
|
||||||
-static void describe(struct commit *cmit, int last_one)
|
-static void describe(struct commit *cmit, int last_one)
|
||||||
++static void describe(char *arg, int last_one)
|
++static void describe(char *arg, int last_one)
|
||||||
{
|
{
|
||||||
+ unsigned char sha1[20];
|
+ unsigned char sha1[20];
|
||||||
+ struct commit *cmit;
|
+ struct commit *cmit;
|
||||||
|
struct commit_list *list;
|
||||||
|
static int initialized = 0;
|
||||||
|
struct commit_name *n;
|
||||||
|
|
||||||
|
+ if (get_sha1(arg, sha1) < 0)
|
||||||
|
+ usage(describe_usage);
|
||||||
|
+ cmit = lookup_commit_reference(sha1);
|
||||||
|
+ if (!cmit)
|
||||||
|
+ usage(describe_usage);
|
||||||
|
+
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = 1;
|
||||||
|
for_each_ref(get_name);
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
1. It is preceded with a "git diff" header, that looks like
|
||||||
|
this (when '-c' option is used):
|
||||||
|
|
||||||
|
diff --combined file
|
||||||
|
+
|
||||||
|
or like this (when '--cc' option is used):
|
||||||
|
|
||||||
|
diff --c file
|
||||||
|
|
||||||
|
2. It is followed by one or more extended header lines
|
||||||
|
(this example shows a merge with two parents):
|
||||||
|
|
||||||
|
index <hash>,<hash>..<hash>
|
||||||
|
mode <mode>,<mode>..<mode>
|
||||||
|
new file mode <mode>
|
||||||
|
deleted file mode <mode>,<mode>
|
||||||
|
+
|
||||||
|
The `mode <mode>,<mode>..<mode>` line appears only if at least one of
|
||||||
|
the <mode> is diferent from the rest. Extended headers with
|
||||||
|
information about detected contents movement (renames and
|
||||||
|
copying detection) are designed to work with diff of two
|
||||||
|
<tree-ish> and are not used by combined diff format.
|
||||||
|
|
||||||
|
3. It is followed by two-line from-file/to-file header
|
||||||
|
|
||||||
|
--- a/file
|
||||||
|
+++ b/file
|
||||||
|
+
|
||||||
|
Similar to two-line header for traditional 'unified' diff
|
||||||
|
format, `/dev/null` is used to signal created or deleted
|
||||||
|
files.
|
||||||
|
|
||||||
|
4. Chunk header format is modified to prevent people from
|
||||||
|
accidentally feeding it to `patch -p1`. Combined diff format
|
||||||
|
was created for review of merge commit changes, and was not
|
||||||
|
meant for apply. The change is similar to the change in the
|
||||||
|
extended 'index' header:
|
||||||
|
|
||||||
|
@@@ <from-file-range> <from-file-range> <to-file-range> @@@
|
||||||
|
+
|
||||||
|
There are (number of parents + 1) `@` characters in the chunk
|
||||||
|
header for combined diff format.
|
||||||
|
|
||||||
Unlike the traditional 'unified' diff format, which shows two
|
Unlike the traditional 'unified' diff format, which shows two
|
||||||
files A and B with a single column that has `-` (minus --
|
files A and B with a single column that has `-` (minus --
|
||||||
appears in A but removed in B), `+` (plus -- missing in A but
|
appears in A but removed in B), `+` (plus -- missing in A but
|
||||||
added to B), or ` ` (space -- unchanged) prefix, this format
|
added to B), or `" "` (space -- unchanged) prefix, this format
|
||||||
compares two or more files file1, file2,... with one file X, and
|
compares two or more files file1, file2,... with one file X, and
|
||||||
shows how X differs from each of fileN. One column for each of
|
shows how X differs from each of fileN. One column for each of
|
||||||
fileN is prepended to the output line to note how X's line is
|
fileN is prepended to the output line to note how X's line is
|
||||||
different from it.
|
different from it.
|
||||||
|
|
||||||
A `-` character in the column N means that the line appears in
|
A `-` character in the column N means that the line appears in
|
||||||
fileN but it does not appear in the last file. A `+` character
|
fileN but it does not appear in the result. A `+` character
|
||||||
in the column N means that the line appears in the last file,
|
in the column N means that the line appears in the last file,
|
||||||
and fileN does not have that line.
|
and fileN does not have that line (in other words, the line was
|
||||||
|
added, from the point of view of that parent).
|
||||||
|
|
||||||
In the above example output, the function signature was changed
|
In the above example output, the function signature was changed
|
||||||
from both files (hence two `-` removals from both file1 and
|
from both files (hence two `-` removals from both file1 and
|
||||||
|
|
|
@ -1,22 +1,7 @@
|
||||||
Everyday GIT With 20 Commands Or So
|
Everyday GIT With 20 Commands Or So
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
GIT suite has over 100 commands, and the manual page for each of
|
<<Basic Repository>> commands are needed by people who have a
|
||||||
them discusses what the command does and how it is used in
|
|
||||||
detail, but until you know what command should be used in order
|
|
||||||
to achieve what you want to do, you cannot tell which manual
|
|
||||||
page to look at, and if you know that already you do not need
|
|
||||||
the manual.
|
|
||||||
|
|
||||||
Does that mean you need to know all of them before you can use
|
|
||||||
git? Not at all. Depending on the role you play, the set of
|
|
||||||
commands you need to know is slightly different, but in any case
|
|
||||||
what you need to learn is far smaller than the full set of
|
|
||||||
commands to carry out your day-to-day work. This document is to
|
|
||||||
serve as a cheat-sheet and a set of pointers for people playing
|
|
||||||
various roles.
|
|
||||||
|
|
||||||
<<Basic Repository>> commands are needed by people who has a
|
|
||||||
repository --- that is everybody, because every working tree of
|
repository --- that is everybody, because every working tree of
|
||||||
git is a repository.
|
git is a repository.
|
||||||
|
|
||||||
|
@ -25,28 +10,27 @@ essential for anybody who makes a commit, even for somebody who
|
||||||
works alone.
|
works alone.
|
||||||
|
|
||||||
If you work with other people, you will need commands listed in
|
If you work with other people, you will need commands listed in
|
||||||
<<Individual Developer (Participant)>> section as well.
|
the <<Individual Developer (Participant)>> section as well.
|
||||||
|
|
||||||
People who play <<Integrator>> role need to learn some more
|
People who play the <<Integrator>> role need to learn some more
|
||||||
commands in addition to the above.
|
commands in addition to the above.
|
||||||
|
|
||||||
<<Repository Administration>> commands are for system
|
<<Repository Administration>> commands are for system
|
||||||
administrators who are responsible to care and feed git
|
administrators who are responsible for the care and feeding
|
||||||
repositories to support developers.
|
of git repositories.
|
||||||
|
|
||||||
|
|
||||||
Basic Repository[[Basic Repository]]
|
Basic Repository[[Basic Repository]]
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
Everybody uses these commands to feed and care git repositories.
|
Everybody uses these commands to maintain git repositories.
|
||||||
|
|
||||||
* gitlink:git-init-db[1] or gitlink:git-clone[1] to create a
|
* gitlink:git-init-db[1] or gitlink:git-clone[1] to create a
|
||||||
new repository.
|
new repository.
|
||||||
|
|
||||||
* gitlink:git-fsck-objects[1] to validate the repository.
|
* gitlink:git-fsck-objects[1] to check the repository for errors.
|
||||||
|
|
||||||
* gitlink:git-prune[1] to garbage collect cruft in the
|
* gitlink:git-prune[1] to remove unused objects in the repository.
|
||||||
repository.
|
|
||||||
|
|
||||||
* gitlink:git-repack[1] to pack loose objects for efficiency.
|
* gitlink:git-repack[1] to pack loose objects for efficiency.
|
||||||
|
|
||||||
|
@ -78,8 +62,8 @@ $ git repack -a -d <1>
|
||||||
$ git prune
|
$ git prune
|
||||||
------------
|
------------
|
||||||
+
|
+
|
||||||
<1> pack all the objects reachable from the refs into one pack
|
<1> pack all the objects reachable from the refs into one pack,
|
||||||
and remove unneeded other packs
|
then remove the other packs.
|
||||||
|
|
||||||
|
|
||||||
Individual Developer (Standalone)[[Individual Developer (Standalone)]]
|
Individual Developer (Standalone)[[Individual Developer (Standalone)]]
|
||||||
|
@ -93,9 +77,6 @@ following commands.
|
||||||
|
|
||||||
* gitlink:git-log[1] to see what happened.
|
* gitlink:git-log[1] to see what happened.
|
||||||
|
|
||||||
* gitlink:git-whatchanged[1] to find out where things have
|
|
||||||
come from.
|
|
||||||
|
|
||||||
* gitlink:git-checkout[1] and gitlink:git-branch[1] to switch
|
* gitlink:git-checkout[1] and gitlink:git-branch[1] to switch
|
||||||
branches.
|
branches.
|
||||||
|
|
||||||
|
@ -120,7 +101,7 @@ following commands.
|
||||||
Examples
|
Examples
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
Extract a tarball and create a working tree and a new repository to keep track of it.::
|
Use a tarball as a starting point for a new repository:
|
||||||
+
|
+
|
||||||
------------
|
------------
|
||||||
$ tar zxf frotz.tar.gz
|
$ tar zxf frotz.tar.gz
|
||||||
|
@ -203,7 +184,7 @@ $ cd my2.6
|
||||||
$ edit/compile/test; git commit -a -s <1>
|
$ edit/compile/test; git commit -a -s <1>
|
||||||
$ git format-patch origin <2>
|
$ git format-patch origin <2>
|
||||||
$ git pull <3>
|
$ git pull <3>
|
||||||
$ git whatchanged -p ORIG_HEAD.. arch/i386 include/asm-i386 <4>
|
$ git log -p ORIG_HEAD.. arch/i386 include/asm-i386 <4>
|
||||||
$ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5>
|
$ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <5>
|
||||||
$ git reset --hard ORIG_HEAD <6>
|
$ git reset --hard ORIG_HEAD <6>
|
||||||
$ git prune <7>
|
$ git prune <7>
|
||||||
|
@ -377,7 +358,7 @@ Run git-daemon to serve /pub/scm from inetd.::
|
||||||
------------
|
------------
|
||||||
$ grep git /etc/inetd.conf
|
$ grep git /etc/inetd.conf
|
||||||
git stream tcp nowait nobody \
|
git stream tcp nowait nobody \
|
||||||
/usr/bin/git-daemon git-daemon --inetd --syslog --export-all /pub/scm
|
/usr/bin/git-daemon git-daemon --inetd --export-all /pub/scm
|
||||||
------------
|
------------
|
||||||
+
|
+
|
||||||
The actual configuration line should be on one line.
|
The actual configuration line should be on one line.
|
||||||
|
@ -397,7 +378,7 @@ service git
|
||||||
wait = no
|
wait = no
|
||||||
user = nobody
|
user = nobody
|
||||||
server = /usr/bin/git-daemon
|
server = /usr/bin/git-daemon
|
||||||
server_args = --inetd --syslog --export-all --base-path=/pub/scm
|
server_args = --inetd --export-all --base-path=/pub/scm
|
||||||
log_on_failure += USERID
|
log_on_failure += USERID
|
||||||
}
|
}
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -165,8 +165,7 @@ git-daemon as inetd server::
|
||||||
+
|
+
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
git stream tcp nowait nobody /usr/bin/git-daemon
|
git stream tcp nowait nobody /usr/bin/git-daemon
|
||||||
git-daemon --inetd --verbose
|
git-daemon --inetd --verbose --export-all
|
||||||
--syslog --export-all
|
|
||||||
/pub/foo /pub/bar
|
/pub/foo /pub/bar
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
@ -179,8 +178,7 @@ git-daemon as inetd server for virtual hosts::
|
||||||
+
|
+
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
git stream tcp nowait nobody /usr/bin/git-daemon
|
git stream tcp nowait nobody /usr/bin/git-daemon
|
||||||
git-daemon --inetd --verbose
|
git-daemon --inetd --verbose --export-all
|
||||||
--syslog --export-all
|
|
||||||
--interpolated-path=/pub/%H%D
|
--interpolated-path=/pub/%H%D
|
||||||
/pub/www.example.org/software
|
/pub/www.example.org/software
|
||||||
/pub/www.example.com/software
|
/pub/www.example.com/software
|
||||||
|
|
|
@ -122,14 +122,30 @@ blobs contained in a commit.
|
||||||
your repository whose object name starts with dae86e.
|
your repository whose object name starts with dae86e.
|
||||||
|
|
||||||
* An output from `git-describe`; i.e. a closest tag, followed by a
|
* An output from `git-describe`; i.e. a closest tag, followed by a
|
||||||
dash, a 'g', and an abbreviated object name.
|
dash, a `g`, and an abbreviated object name.
|
||||||
|
|
||||||
* A symbolic ref name. E.g. 'master' typically means the commit
|
* A symbolic ref name. E.g. 'master' typically means the commit
|
||||||
object referenced by $GIT_DIR/refs/heads/master. If you
|
object referenced by $GIT_DIR/refs/heads/master. If you
|
||||||
happen to have both heads/master and tags/master, you can
|
happen to have both heads/master and tags/master, you can
|
||||||
explicitly say 'heads/master' to tell git which one you mean.
|
explicitly say 'heads/master' to tell git which one you mean.
|
||||||
|
When ambiguous, a `<name>` is disambiguated by taking the
|
||||||
|
first match in the following rules:
|
||||||
|
|
||||||
* A suffix '@' followed by a date specification enclosed in a brace
|
. if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
|
||||||
|
useful only for `HEAD`, `FETCH_HEAD` and `MERGE_HEAD`);
|
||||||
|
|
||||||
|
. otherwise, `$GIT_DIR/refs/<name>` if exists;
|
||||||
|
|
||||||
|
. otherwise, `$GIT_DIR/refs/tags/<name>` if exists;
|
||||||
|
|
||||||
|
. otherwise, `$GIT_DIR/refs/heads/<name>` if exists;
|
||||||
|
|
||||||
|
. otherwise, `$GIT_DIR/refs/remotes/<name>` if exists;
|
||||||
|
|
||||||
|
. otherwise, `$GIT_DIR/refs/remotes/<name>/HEAD` if exists.
|
||||||
|
|
||||||
|
* A ref followed by the suffix '@' with a date specification
|
||||||
|
enclosed in a brace
|
||||||
pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
|
pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
|
||||||
second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
|
second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
|
||||||
of the ref at a prior point in time. This suffix may only be
|
of the ref at a prior point in time. This suffix may only be
|
||||||
|
@ -146,8 +162,9 @@ blobs contained in a commit.
|
||||||
* A suffix '{tilde}<n>' to a revision parameter means the commit
|
* A suffix '{tilde}<n>' to a revision parameter means the commit
|
||||||
object that is the <n>th generation grand-parent of the named
|
object that is the <n>th generation grand-parent of the named
|
||||||
commit object, following only the first parent. I.e. rev~3 is
|
commit object, following only the first parent. I.e. rev~3 is
|
||||||
equivalent to rev{caret}{caret}{caret} which is equivalent to\
|
equivalent to rev{caret}{caret}{caret} which is equivalent to
|
||||||
rev{caret}1{caret}1{caret}1.
|
rev{caret}1{caret}1{caret}1. See below for a illustration of
|
||||||
|
the usage of this form.
|
||||||
|
|
||||||
* A suffix '{caret}' followed by an object type name enclosed in
|
* A suffix '{caret}' followed by an object type name enclosed in
|
||||||
brace pair (e.g. `v0.99.8{caret}\{commit\}`) means the object
|
brace pair (e.g. `v0.99.8{caret}\{commit\}`) means the object
|
||||||
|
|
|
@ -489,6 +489,12 @@ static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long
|
||||||
printf(" -%lu,%lu", l0, l1-l0);
|
printf(" -%lu,%lu", l0, l1-l0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hunk_comment_line(const char *bol)
|
||||||
|
{
|
||||||
|
int ch = *bol & 0xff;
|
||||||
|
return (isalpha(ch) || ch == '_' || ch == '$');
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
|
static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
|
||||||
int use_color)
|
int use_color)
|
||||||
{
|
{
|
||||||
|
@ -508,8 +514,13 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
|
||||||
struct sline *sl = &sline[lno];
|
struct sline *sl = &sline[lno];
|
||||||
unsigned long hunk_end;
|
unsigned long hunk_end;
|
||||||
unsigned long rlines;
|
unsigned long rlines;
|
||||||
while (lno <= cnt && !(sline[lno].flag & mark))
|
const char *hunk_comment = NULL;
|
||||||
|
|
||||||
|
while (lno <= cnt && !(sline[lno].flag & mark)) {
|
||||||
|
if (hunk_comment_line(sline[lno].bol))
|
||||||
|
hunk_comment = sline[lno].bol;
|
||||||
lno++;
|
lno++;
|
||||||
|
}
|
||||||
if (cnt < lno)
|
if (cnt < lno)
|
||||||
break;
|
break;
|
||||||
else {
|
else {
|
||||||
|
@ -526,6 +537,22 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
|
||||||
show_parent_lno(sline, lno, hunk_end, i);
|
show_parent_lno(sline, lno, hunk_end, i);
|
||||||
printf(" +%lu,%lu ", lno+1, rlines);
|
printf(" +%lu,%lu ", lno+1, rlines);
|
||||||
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
|
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
|
||||||
|
|
||||||
|
if (hunk_comment) {
|
||||||
|
int comment_end = 0;
|
||||||
|
for (i = 0; i < 40; i++) {
|
||||||
|
int ch = hunk_comment[i] & 0xff;
|
||||||
|
if (!ch || ch == '\n')
|
||||||
|
break;
|
||||||
|
if (!isspace(ch))
|
||||||
|
comment_end = i;
|
||||||
|
}
|
||||||
|
if (comment_end)
|
||||||
|
putchar(' ');
|
||||||
|
for (i = 0; i < comment_end; i++)
|
||||||
|
putchar(hunk_comment[i]);
|
||||||
|
}
|
||||||
|
|
||||||
printf("%s\n", c_reset);
|
printf("%s\n", c_reset);
|
||||||
while (lno < hunk_end) {
|
while (lno < hunk_end) {
|
||||||
struct lline *ll;
|
struct lline *ll;
|
||||||
|
@ -707,6 +734,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
||||||
int use_color = opt->color_diff;
|
int use_color = opt->color_diff;
|
||||||
const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
|
const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
|
||||||
const char *c_reset = diff_get_color(use_color, DIFF_RESET);
|
const char *c_reset = diff_get_color(use_color, DIFF_RESET);
|
||||||
|
int added = 0;
|
||||||
|
int deleted = 0;
|
||||||
|
|
||||||
if (rev->loginfo)
|
if (rev->loginfo)
|
||||||
show_log(rev, opt->msg_sep);
|
show_log(rev, opt->msg_sep);
|
||||||
|
@ -722,7 +751,10 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
||||||
printf("..%s%s\n", abb, c_reset);
|
printf("..%s%s\n", abb, c_reset);
|
||||||
|
|
||||||
if (mode_differs) {
|
if (mode_differs) {
|
||||||
int added = !!elem->mode;
|
deleted = !elem->mode;
|
||||||
|
|
||||||
|
/* We say it was added if nobody had it */
|
||||||
|
added = !deleted;
|
||||||
for (i = 0; added && i < num_parent; i++)
|
for (i = 0; added && i < num_parent; i++)
|
||||||
if (elem->parent[i].status !=
|
if (elem->parent[i].status !=
|
||||||
DIFF_STATUS_ADDED)
|
DIFF_STATUS_ADDED)
|
||||||
|
@ -731,7 +763,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
||||||
printf("%snew file mode %06o",
|
printf("%snew file mode %06o",
|
||||||
c_meta, elem->mode);
|
c_meta, elem->mode);
|
||||||
else {
|
else {
|
||||||
if (!elem->mode)
|
if (deleted)
|
||||||
printf("%sdeleted file ", c_meta);
|
printf("%sdeleted file ", c_meta);
|
||||||
printf("mode ");
|
printf("mode ");
|
||||||
for (i = 0; i < num_parent; i++) {
|
for (i = 0; i < num_parent; i++) {
|
||||||
|
@ -743,8 +775,14 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
||||||
}
|
}
|
||||||
printf("%s\n", c_reset);
|
printf("%s\n", c_reset);
|
||||||
}
|
}
|
||||||
dump_quoted_path("--- a/", elem->path, c_meta, c_reset);
|
if (added)
|
||||||
dump_quoted_path("+++ b/", elem->path, c_meta, c_reset);
|
dump_quoted_path("--- /dev/", "null", c_meta, c_reset);
|
||||||
|
else
|
||||||
|
dump_quoted_path("--- a/", elem->path, c_meta, c_reset);
|
||||||
|
if (deleted)
|
||||||
|
dump_quoted_path("+++ /dev/", "null", c_meta, c_reset);
|
||||||
|
else
|
||||||
|
dump_quoted_path("+++ b/", elem->path, c_meta, c_reset);
|
||||||
dump_sline(sline, cnt, num_parent, opt->color_diff);
|
dump_sline(sline, cnt, num_parent, opt->color_diff);
|
||||||
}
|
}
|
||||||
free(result);
|
free(result);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче