From cc1793e2cef20a06aed6d8987c3361e7fbd09305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Hasselstr=C3=B6m?= Date: Fri, 4 May 2007 09:03:22 +0200 Subject: [PATCH 01/10] Fix markup in git-svn man page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the existing markup was just plain broken, and some subcommand options weren't indented properly. Signed-off-by: Karl Hasselström Signed-off-by: Junio C Hamano --- Documentation/git-svn.txt | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 62d7ef8be4..820a2c308e 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -38,32 +38,30 @@ COMMANDS argument. Normally this command initializes the current directory. --T:: ---trunk=:: --t:: ---tags=:: --b:: ---branches=:: +-T;; +--trunk=;; +-t;; +--tags=;; +-b;; +--branches=;; 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=:: +--rewrite-root=;; Set the 'rewriteRoot' option in the [svn-remote] config. ---username=:: +--username=;; 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=;; 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 From 171af11082d41f8e7a678e1e1a4ec6f610d01cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Hasselstr=C3=B6m?= Date: Thu, 3 May 2007 07:51:35 +0200 Subject: [PATCH 02/10] Add --no-rebase option to git-svn dcommit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn dcommit exports commits to Subversion, then imports them back to git again, and last but not least rebases or resets HEAD to the last of the new commits. I guess this rebasing is convenient when using just git, but when the commits to be exported are managed by StGIT, it's really annoying. So add an option to disable this behavior. And document it, too! Signed-off-by: Karl Hasselström Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- Documentation/git-svn.txt | 3 +++ git-svn.perl | 33 ++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 820a2c308e..c0d7d9597b 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -119,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':: diff --git a/git-svn.perl b/git-svn.perl index 6657e100fb..3c4f490b74 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -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 { From 71f4b1834a8b4d1cb24ea326ca4a3fcc02796a5a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 May 2007 11:27:10 -0700 Subject: [PATCH 03/10] Mention version 1.5.1 in tutorial and user-manual Most other documentation will frequently be read from an installation of git so will naturally be associated with the installed version. But these two documents in particular are often read from web pages while users are still exploring git. It's important to mention version 1.5.1 since these documents provide example commands that won't work with previous versions of git. Signed-off-by: Junio C Hamano --- Documentation/tutorial.txt | 4 ++-- Documentation/user-manual.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index e978562d6e..99efce4576 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -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. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 9c4c41df5a..dff438f768 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -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. From 3b559eab55693111e0922cd3dd41bfdba2e22989 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 5 May 2007 00:48:35 +0200 Subject: [PATCH 04/10] diff format documentation: describe raw combined diff format Add description of raw combined diff format to diff-formats.txt, as "diff format for merges" section, before "Generating patches..." section. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- Documentation/diff-format.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 378e72f38f..e38a1f1405 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -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 -------------------------- From e330a406cd20cf45a6816929155181c37678bc47 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 5 May 2007 15:18:03 -0700 Subject: [PATCH 05/10] Fix --boundary output "git log --boundary" incorrectly honoured the option only when "left-right" was enabled. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- log-tree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/log-tree.c b/log-tree.c index 8797aa14c4..dbd06490f9 100644 --- a/log-tree.c +++ b/log-tree.c @@ -218,10 +218,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('>'); From dd166aa8e52dba39a3087b8012113af331d3110b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 5 May 2007 09:13:26 -0700 Subject: [PATCH 06/10] blame: Notice a wholesale incorporation of an existing file. The -C option to blame tries to find a section of a preimage file by running diff against the lines whose origin is still unknown, and excluding the different parts. The code however did not cover the case where the tail part of the section matched, which we handle for the normal non-move/copy codepath. This breakage was most visible when preimage file matches in its entirety and failed to pass blame in such a case. Signed-off-by: Junio C Hamano --- builtin-blame.c | 52 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index 8919b028e6..f8843e6340 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -890,6 +890,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 @@ -922,26 +955,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); } From c63777c0d7687a1edff2c0da307ad8ac1d75c8f6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 5 May 2007 21:18:57 -0700 Subject: [PATCH 07/10] blame: -C -C -C When you do this, existing "blame -C -C" would not find that the latter half of the file2 came from the existing file1: ... both file1 and file2 are tracked ... $ cat file1 >>file2 $ git add file1 file2 $ git commit This is because we avoid the expensive find-copies-harder code that makes unchanged file (in this case, file1) as a candidate for copy & paste source when annotating an existing file (file2). The third -C now allows it. However, this obviously makes the process very expensive. We've actually seen this patch before, but I dismissed it because it covers such a narrow (and arguably stupid) corner case. Signed-off-by: Junio C Hamano --- builtin-blame.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index f8843e6340..65d029a773 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -55,6 +55,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 @@ -1079,8 +1080,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)) @@ -2127,6 +2129,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; From c2a063691e1dcec137ed1f0def406d3bf3567e71 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 5 May 2007 22:36:19 -0700 Subject: [PATCH 08/10] Add test for blame corner cases. Signed-off-by: Junio C Hamano --- t/t8003-blame.sh | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 t/t8003-blame.sh diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh new file mode 100755 index 0000000000..db51b3a6bb --- /dev/null +++ b/t/t8003-blame.sh @@ -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 From cf593cc41828c6fc0a2cec50ddac0713ea8a07ec Mon Sep 17 00:00:00 2001 From: James Bowes Date: Sat, 5 May 2007 14:23:12 -0400 Subject: [PATCH 09/10] Documentation: fix typo in git-remote.txt Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- Documentation/git-remote.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index a9fb6a9a5e..3dde7134a5 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -40,7 +40,7 @@ With `-t ` option, instead of the default glob refspec for the remote to track all branches under `$GIT_DIR/remotes//`, a refspec to track only `` is created. You can give more than one `-t ` to track -multiple branche without grabbing all branches. +multiple branches without grabbing all branches. + With `-m ` option, `$GIT_DIR/remotes//HEAD` is set up to point at remote's `` branch instead of whatever From e102d4353d7cfd69a597cd976eabdcb74641be69 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 4 May 2007 23:51:32 +0200 Subject: [PATCH 10/10] Small correction in reading of commit headers Check if a line of the header has enough characters to possibly contain the requested prefix. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- commit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commit.c b/commit.c index eb911f44d7..7d78e786e9 100644 --- a/commit.c +++ b/commit.c @@ -640,7 +640,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);