1
0
mirror of https://github.com/git/git.git synced 2024-09-28 04:10:41 +02:00

Merge branch 'maint'

* maint:
  Small correction in reading of commit headers
  Documentation: fix typo in git-remote.txt
  Add test for blame corner cases.
  blame: -C -C -C
  blame: Notice a wholesale incorporation of an existing file.
  Fix --boundary output
  diff format documentation: describe raw combined diff format
  Mention version 1.5.1 in tutorial and user-manual
  Add --no-rebase option to git-svn dcommit
  Fix markup in git-svn man page
This commit is contained in:
Junio C Hamano 2007-05-06 00:21:03 -07:00
commit 125a5f1c2a
10 changed files with 253 additions and 58 deletions

View File

@ -59,6 +59,28 @@ When `-z` option is not used, TAB, LF, and backslash characters
in pathnames are represented as `\t`, `\n`, and `\\`,
respectively.
diff format for merges
----------------------
"git-diff-tree" and "git-diff-files" can take '-c' or '--cc' option
to generate diff output also for merge commits. The output differs
from the format described above in the following way:
. there is a colon for each parent
. there are more "src" modes and "src" sha1
. status is concatenated status characters for each parent
. no optional "score" number
. single path, only for "dst"
Example:
------------------------------------------------
::100644 100644 100644 fabadb8... cc95eb0... 4866510... MM describe.c
------------------------------------------------
Note that 'combined diff' lists only files which were modified from
all parents.
Generating patches with -p
--------------------------

View File

@ -40,7 +40,7 @@ With `-t <branch>` option, instead of the default glob
refspec for the remote to track all branches under
`$GIT_DIR/remotes/<name>/`, a refspec to track only `<branch>`
is created. You can give more than one `-t <branch>` to track
multiple branche without grabbing all branches.
multiple branches without grabbing all branches.
+
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
up to point at remote's `<master>` branch instead of whatever

View File

@ -38,32 +38,30 @@ COMMANDS
argument. Normally this command initializes the current
directory.
-T<trunk_subdir>::
--trunk=<trunk_subdir>::
-t<tags_subdir>::
--tags=<tags_subdir>::
-b<branches_subdir>::
--branches=<branches_subdir>::
-T<trunk_subdir>;;
--trunk=<trunk_subdir>;;
-t<tags_subdir>;;
--tags=<tags_subdir>;;
-b<branches_subdir>;;
--branches=<branches_subdir>;;
These are optional command-line options for init. Each of
these flags can point to a relative repository path
(--tags=project/tags') or a full url
(--tags=https://foo.org/project/tags)
--no-metadata::
--no-metadata;;
Set the 'noMetadata' option in the [svn-remote] config.
--use-svm-props::
--use-svm-props;;
Set the 'useSvmProps' option in the [svn-remote] config.
--use-svnsync-props::
--use-svnsync-props;;
Set the 'useSvnsyncProps' option in the [svn-remote] config.
--rewrite-root=<URL>::
--rewrite-root=<URL>;;
Set the 'rewriteRoot' option in the [svn-remote] config.
--username=<USER>::
--username=<USER>;;
For transports that SVN handles authentication for (http,
https, and plain svn), specify the username. For other
transports (eg svn+ssh://), you must include the username in
the URL, eg svn+ssh://foo@svn.bar.com/project
--prefix=<prefix>::
--prefix=<prefix>;;
This allows one to specify a prefix which is prepended
to the names of remotes if trunk/branches/tags are
specified. The prefix does not automatically include a
@ -73,7 +71,6 @@ COMMANDS
repository.
'fetch'::
Fetch unfetched revisions from the Subversion remote we are
tracking. The name of the [svn-remote "..."] section in the
.git/config file may be specified as an optional command-line
@ -104,14 +101,11 @@ accepts. However '--fetch-all' only fetches from the current
Like 'git-rebase'; this requires that the working tree be clean
and have no uncommitted changes.
+
--
-l;;
--local;;
Do not fetch remotely; only run 'git-rebase' against the
last fetched commit from the upstream SVN.
--
+
'dcommit'::
Commit each diff from a specified head directly to the SVN
@ -125,6 +119,9 @@ and have no uncommitted changes.
alternative to HEAD.
This is advantageous over 'set-tree' (below) because it produces
cleaner, more linear history.
+
--no-rebase;;
After committing, do not rebase or reset.
--
'log'::

View File

@ -1,5 +1,5 @@
A tutorial introduction to git
==============================
A tutorial introduction to git (for version 1.5.1 or newer)
===========================================================
This tutorial explains how to import a new project into git, make
changes to it, and share changes with other developers.

View File

@ -1,5 +1,5 @@
Git User's Manual
_________________
Git User's Manual (for version 1.5.1 or newer)
______________________________________________
This manual is designed to be readable by someone with basic unix
command-line skills, but no previous knowledge of git.

View File

@ -59,6 +59,7 @@ static int num_commits;
#define PICKAXE_BLAME_MOVE 01
#define PICKAXE_BLAME_COPY 02
#define PICKAXE_BLAME_COPY_HARDER 04
#define PICKAXE_BLAME_COPY_HARDEST 010
/*
* blame for a blame_entry with score lower than these thresholds
@ -894,6 +895,39 @@ static void copy_split_if_better(struct scoreboard *sb,
memcpy(best_so_far, this, sizeof(struct blame_entry [3]));
}
/*
* We are looking at a part of the final image represented by
* ent (tlno and same are offset by ent->s_lno).
* tlno is where we are looking at in the final image.
* up to (but not including) same match preimage.
* plno is where we are looking at in the preimage.
*
* <-------------- final image ---------------------->
* <------ent------>
* ^tlno ^same
* <---------preimage----->
* ^plno
*
* All line numbers are 0-based.
*/
static void handle_split(struct scoreboard *sb,
struct blame_entry *ent,
int tlno, int plno, int same,
struct origin *parent,
struct blame_entry *split)
{
if (ent->num_lines <= tlno)
return;
if (tlno < same) {
struct blame_entry this[3];
tlno += ent->s_lno;
same += ent->s_lno;
split_overlap(this, ent, tlno, plno, same, parent);
copy_split_if_better(sb, split, this);
decref_split(this);
}
}
/*
* Find the lines from parent that are the same as ent so that
* we can pass blames to it. file_p has the blob contents for
@ -926,26 +960,21 @@ static void find_copy_in_blob(struct scoreboard *sb,
patch = compare_buffer(file_p, &file_o, 1);
/*
* file_o is a part of final image we are annotating.
* file_p partially may match that image.
*/
memset(split, 0, sizeof(struct blame_entry [3]));
plno = tlno = 0;
for (i = 0; i < patch->num; i++) {
struct chunk *chunk = &patch->chunks[i];
/* tlno to chunk->same are the same as ent */
if (ent->num_lines <= tlno)
break;
if (tlno < chunk->same) {
struct blame_entry this[3];
split_overlap(this, ent,
tlno + ent->s_lno, plno,
chunk->same + ent->s_lno,
parent);
copy_split_if_better(sb, split, this);
decref_split(this);
}
handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
plno = chunk->p_next;
tlno = chunk->t_next;
}
/* remainder, if any, all match the preimage */
handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
free_patch(patch);
}
@ -1055,8 +1084,9 @@ static int find_copy_in_parent(struct scoreboard *sb,
* and this code needs to be after diff_setup_done(), which
* usually makes find-copies-harder imply copy detection.
*/
if ((opt & PICKAXE_BLAME_COPY_HARDER) &&
(!porigin || strcmp(target->path, porigin->path)))
if ((opt & PICKAXE_BLAME_COPY_HARDEST)
|| ((opt & PICKAXE_BLAME_COPY_HARDER)
&& (!porigin || strcmp(target->path, porigin->path))))
diff_opts.find_copies_harder = 1;
if (is_null_sha1(target->commit->object.sha1))
@ -2136,6 +2166,15 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
blame_move_score = parse_score(arg+2);
}
else if (!prefixcmp(arg, "-C")) {
/*
* -C enables copy from removed files;
* -C -C enables copy from existing files, but only
* when blaming a new file;
* -C -C -C enables copy from existing files for
* everybody
*/
if (opt & PICKAXE_BLAME_COPY_HARDER)
opt |= PICKAXE_BLAME_COPY_HARDEST;
if (opt & PICKAXE_BLAME_COPY)
opt |= PICKAXE_BLAME_COPY_HARDER;
opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;

View File

@ -638,7 +638,9 @@ static char *get_header(const struct commit *commit, const char *key)
next = NULL;
} else
next = eol + 1;
if (!strncmp(line, key, key_len) && line[key_len] == ' ') {
if (eol - line > key_len &&
!strncmp(line, key, key_len) &&
line[key_len] == ' ') {
int len = eol - line - key_len;
char *ret = xmalloc(len);
memcpy(ret, line + key_len + 1, len - 1);

View File

@ -55,7 +55,7 @@ $sha1_short = qr/[a-f\d]{4,40}/;
my ($_stdin, $_help, $_edit,
$_message, $_file,
$_template, $_shared,
$_version, $_fetch_all,
$_version, $_fetch_all, $_no_rebase,
$_merge, $_strategy, $_dry_run, $_local,
$_prefix, $_no_checkout, $_verbose);
$Git::SVN::_follow_parent = 1;
@ -114,6 +114,7 @@ my %cmd = (
'verbose|v' => \$_verbose,
'dry-run|n' => \$_dry_run,
'fetch-all|all' => \$_fetch_all,
'no-rebase' => \$_no_rebase,
%cmt_opts, %fc_opts } ],
'set-tree' => [ \&cmd_set_tree,
"Set an SVN repository to a git tree-ish",
@ -413,21 +414,23 @@ sub cmd_dcommit {
return;
}
$_fetch_all ? $gs->fetch_all : $gs->fetch;
# we always want to rebase against the current HEAD, not any
# head that was passed to us
my @diff = command('diff-tree', 'HEAD', $gs->refname, '--');
my @finish;
if (@diff) {
@finish = rebase_cmd();
print STDERR "W: HEAD and ", $gs->refname, " differ, ",
"using @finish:\n", "@diff";
} else {
print "No changes between current HEAD and ",
$gs->refname, "\nResetting to the latest ",
$gs->refname, "\n";
@finish = qw/reset --mixed/;
unless ($_no_rebase) {
# we always want to rebase against the current HEAD, not any
# head that was passed to us
my @diff = command('diff-tree', 'HEAD', $gs->refname, '--');
my @finish;
if (@diff) {
@finish = rebase_cmd();
print STDERR "W: HEAD and ", $gs->refname, " differ, ",
"using @finish:\n", "@diff";
} else {
print "No changes between current HEAD and ",
$gs->refname, "\nResetting to the latest ",
$gs->refname, "\n";
@finish = qw/reset --mixed/;
}
command_noisy(@finish, $gs->refname);
}
command_noisy(@finish, $gs->refname);
}
sub cmd_find_rev {

View File

@ -244,10 +244,10 @@ void show_log(struct rev_info *opt, const char *sep)
stdout);
if (opt->commit_format != CMIT_FMT_ONELINE)
fputs("commit ", stdout);
if (opt->left_right) {
if (commit->object.flags & BOUNDARY)
putchar('-');
else if (commit->object.flags & SYMMETRIC_LEFT)
if (commit->object.flags & BOUNDARY)
putchar('-');
else if (opt->left_right) {
if (commit->object.flags & SYMMETRIC_LEFT)
putchar('<');
else
putchar('>');

132
t/t8003-blame.sh Executable file
View File

@ -0,0 +1,132 @@
#!/bin/sh
test_description='git blame corner cases'
. ./test-lib.sh
pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/'
test_expect_success setup '
echo A A A A A >one &&
echo B B B B B >two &&
echo C C C C C >tres &&
echo ABC >mouse &&
git add one two tres mouse &&
test_tick &&
GIT_AUTHOR_NAME=Initial git commit -m Initial &&
cat one >uno &&
mv two dos &&
cat one >>tres &&
echo DEF >>mouse
git add uno dos tres mouse &&
test_tick &&
GIT_AUTHOR_NAME=Second git commit -a -m Second &&
echo GHIJK >>mouse &&
git add mouse &&
test_tick &&
GIT_AUTHOR_NAME=Third git commit -m Third &&
cat mouse >cow &&
git add cow &&
test_tick &&
GIT_AUTHOR_NAME=Fourth git commit -m Fourth &&
{
echo ABC
echo DEF
echo XXXX
echo GHIJK
} >cow &&
git add cow &&
test_tick &&
GIT_AUTHOR_NAME=Fifth git commit -m Fifth
'
test_expect_success 'straight copy without -C' '
git blame uno | grep Second
'
test_expect_success 'straight move without -C' '
git blame dos | grep Initial
'
test_expect_success 'straight copy with -C' '
git blame -C1 uno | grep Second
'
test_expect_success 'straight move with -C' '
git blame -C1 dos | grep Initial
'
test_expect_success 'straight copy with -C -C' '
git blame -C -C1 uno | grep Initial
'
test_expect_success 'straight move with -C -C' '
git blame -C -C1 dos | grep Initial
'
test_expect_success 'append without -C' '
git blame -L2 tres | grep Second
'
test_expect_success 'append with -C' '
git blame -L2 -C1 tres | grep Second
'
test_expect_success 'append with -C -C' '
git blame -L2 -C -C1 tres | grep Second
'
test_expect_success 'append with -C -C -C' '
git blame -L2 -C -C -C1 tres | grep Initial
'
test_expect_success 'blame wholesale copy' '
git blame -f -C -C1 HEAD^ -- cow | sed -e "$pick_fc" >current &&
{
echo mouse-Initial
echo mouse-Second
echo mouse-Third
} >expected &&
diff -u expected current
'
test_expect_success 'blame wholesale copy and more' '
git blame -f -C -C1 HEAD -- cow | sed -e "$pick_fc" >current &&
{
echo mouse-Initial
echo mouse-Second
echo cow-Fifth
echo mouse-Third
} >expected &&
diff -u expected current
'
test_done