Merge branch 'jc/3way' into next

* jc/3way:
  git-merge: preserve and merge local changes when doing fast forward
  git-svn: avoid fetching files twice in the same revision
  git-merge: fix confusion between tag and branch
  De-emphasise the symbolic link documentation.
  git-diff: Introduce --index and deprecate --cached.
  ls-files: Give hints when errors happen.
  pack-objects: remove redundent status information
  gitk: Fix enabling/disabling of menu items on Mac OS X
This commit is contained in:
Junio C Hamano
2006-12-02 17:28:52 -08:00
9 changed files with 98 additions and 45 deletions

View File

@@ -22,8 +22,10 @@ the number of trees given to the command.
* When one <tree-ish> is given, the working tree and the named
tree are compared, using `git-diff-index`. The option
`--cached` can be given to compare the index file and
`--index` can be given to compare the index file and
the named tree.
`--cached` is a deprecated alias for `--index`. It's use is
discouraged.
* When two <tree-ish>s are given, these two trees are compared
using `git-diff-tree`.
@@ -47,7 +49,7 @@ Various ways to check your working tree::
+
------------
$ git diff <1>
$ git diff --cached <2>
$ git diff --index <2>
$ git diff HEAD <3>
------------
+

View File

@@ -19,29 +19,22 @@ argument to see on which branch your working tree is on.
Give two arguments, create or update a symbolic ref <name> to
point at the given branch <ref>.
Traditionally, `.git/HEAD` is a symlink pointing at
`refs/heads/master`. When we want to switch to another branch,
we did `ln -sf refs/heads/newbranch .git/HEAD`, and when we want
A symbolic ref is a regular file that stores a string that
begins with `ref: refs/`. For example, your `.git/HEAD` is
a regular file whose contents is `ref: refs/heads/master`.
NOTES
-----
In the past, `.git/HEAD` was a symbolic link pointing at
`refs/heads/master`. When we wanted to switch to another branch,
we did `ln -sf refs/heads/newbranch .git/HEAD`, and when we wanted
to find out which branch we are on, we did `readlink .git/HEAD`.
This was fine, and internally that is what still happens by
default, but on platforms that do not have working symlinks,
or that do not have the `readlink(1)` command, this was a bit
cumbersome. On some platforms, `ln -sf` does not even work as
advertised (horrors).
A symbolic ref can be a regular file that stores a string that
begins with `ref: refs/`. For example, your `.git/HEAD` *can*
be a regular file whose contents is `ref: refs/heads/master`.
This can be used on a filesystem that does not support symbolic
links. Instead of doing `readlink .git/HEAD`, `git-symbolic-ref
HEAD` can be used to find out which branch we are on. To point
the HEAD to `newbranch`, instead of `ln -sf refs/heads/newbranch
.git/HEAD`, `git-symbolic-ref HEAD refs/heads/newbranch` can be
used.
Currently, .git/HEAD uses a regular file symbolic ref on Cygwin,
and everywhere else it is implemented as a symlink. This can be
changed at compilation time.
advertised (horrors). Therefore symbolic links are now deprecated
and symbolic refs are used by default.
Author
------

View File

@@ -137,7 +137,7 @@ static int builtin_diff_index(struct rev_info *revs,
int cached = 0;
while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--cached"))
if (!strcmp(arg, "--index") || !strcmp(arg, "--cached"))
cached = 1;
else
usage(builtin_diff_usage);

View File

@@ -487,10 +487,14 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
for (num = 0; pathspec[num]; num++) {
if (ps_matched[num])
continue;
error("pathspec '%s' did not match any.",
error("pathspec '%s' did not match any file(s) known to git.",
pathspec[num] + prefix_offset);
errors++;
}
if (errors)
fprintf(stderr, "Did you forget to 'git add'?\n");
return errors ? 1 : 0;
}

View File

@@ -514,6 +514,8 @@ static void write_pack_file(void)
if (do_progress)
fputc('\n', stderr);
done:
if (written != nr_result)
die("wrote %d objects while expecting %d", written, nr_result);
sha1close(f, pack_file_sha1, 1);
}
@@ -1662,7 +1664,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
}
}
if (progress)
fprintf(stderr, "Total %d, written %d (delta %d), reused %d (delta %d)\n",
nr_result, written, written_delta, reused, reused_delta);
fprintf(stderr, "Total %d (delta %d), reused %d (delta %d)\n",
written, written_delta, reused, reused_delta);
return 0;
}

View File

@@ -168,6 +168,9 @@ else
exit 1 ;;
esac
# First stash away the local changes
git diff-index --binary -p HEAD >"$GIT_DIR"/LOCAL_DIFF
# Match the index to the working tree, and do a three-way.
git diff-files --name-only | git update-index --remove --stdin &&
work=`git write-tree` &&
@@ -195,6 +198,10 @@ else
sed -e 's/^[0-7]* [0-9a-f]* /'"0 $z40 /"
echo "$unmerged"
) | git update-index --index-info
echo >&2 "Conflicts in locally modified files:"
git diff --name-only --diff-filter=U >&2
echo >&2 "Your local changes are found in $GIT_DIR/LOCAL_DIFF"
;;
esac
exit 0

View File

@@ -91,6 +91,51 @@ finish () {
esac
}
merge_local_changes () {
merge_error=$(git-read-tree -m -u $1 $2 2>&1) || (
# First stash away the local changes
git diff-index --binary -p HEAD >"$GIT_DIR"/LOCAL_DIFF
# Match the index to the working tree, and do a three-way.
git diff-files --name-only |
git update-index --remove --stdin &&
work=`git write-tree` &&
git read-tree --reset -u $2 &&
git read-tree -m -u --aggressive $1 $2 $work || exit
echo >&2 "Carrying local changes forward."
if result=`git write-tree 2>/dev/null`
then
echo >&2 "Trivially automerged."
else
git merge-index -o git-merge-one-file -a
fi
# Do not register the cleanly merged paths in the index
# yet; this is not a real merge before committing, but
# just carrying the working tree changes along.
unmerged=`git ls-files -u`
git read-tree --reset $2
case "$unmerged" in
'') ;;
*)
(
z40=0000000000000000000000000000000000000000
echo "$unmerged" |
sed -e 's/^[0-7]* [0-9a-f]* /'"0 $z40 /"
echo "$unmerged"
) | git update-index --index-info
echo >&2 "Conflicts in locally modified files:"
git diff --name-only --diff-filter=U >&2
echo >&2 "Your local changes are found in $GIT_DIR/LOCAL_DIFF"
;;
esac
exit 0
)
}
case "$#" in 0) usage ;; esac
rloga= have_message=
@@ -189,13 +234,13 @@ else
merge_name=$(for remote
do
rh=$(git-rev-parse --verify "$remote"^0 2>/dev/null) &&
if git show-ref -q --verify "refs/heads/$remote"
bh=$(git show-ref -s --verify "refs/heads/$remote") &&
if test "$rh" = "$bh"
then
what=branch
echo "$rh branch '$remote' of ."
else
what=commit
fi &&
echo "$rh $what '$remote'"
echo "$rh commit '$remote'"
fi
done | git-fmt-merge-msg
)
merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
@@ -264,7 +309,7 @@ f,*)
echo "Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)"
git-update-index --refresh 2>/dev/null
new_head=$(git-rev-parse --verify "$1^0") &&
git-read-tree -u -v -m $head "$new_head" &&
merge_local_changes $head $new_head &&
finish "$new_head" "Fast forward"
dropsave
exit 0

View File

@@ -2982,7 +2982,7 @@ sub libsvn_fetch_delta {
sub libsvn_fetch_full {
my ($last_commit, $paths, $rev, $author, $date, $msg) = @_;
open my $gui, '| git-update-index -z --index-info' or croak $!;
my @amr;
my %amr;
my $p = $SVN->{svn_path};
foreach my $f (keys %$paths) {
my $m = $paths->{$f}->action();
@@ -3001,7 +3001,7 @@ sub libsvn_fetch_full {
my $t = $SVN->check_path($f, $rev, $pool);
if ($t == $SVN::Node::file) {
if ($m =~ /^[AMR]$/) {
push @amr, [ $m, $f ];
$amr{$f} = $m;
} else {
die "Unrecognized action: $m, ($f r$rev)\n";
}
@@ -3009,13 +3009,13 @@ sub libsvn_fetch_full {
my @traversed = ();
libsvn_traverse($gui, '', $f, $rev, \@traversed);
foreach (@traversed) {
push @amr, [ $m, $_ ]
$amr{$_} = $m;
}
}
$pool->clear;
}
foreach (@amr) {
libsvn_get_file($gui, $_->[1], $rev, $_->[0]);
foreach (keys %amr) {
libsvn_get_file($gui, $_, $rev, $amr{$_});
}
close $gui or croak $?;
return libsvn_log_entry($rev, $author, $date, $msg, [$last_commit]);

20
gitk
View File

@@ -554,7 +554,7 @@ proc makewindow {} {
pack .ctop.top.lbar.vlabel -side left -fill y
global viewhlmenu selectedhlview
set viewhlmenu [tk_optionMenu .ctop.top.lbar.vhl selectedhlview None]
$viewhlmenu entryconf 0 -command delvhighlight
$viewhlmenu entryconf None -command delvhighlight
$viewhlmenu conf -font $uifont
.ctop.top.lbar.vhl conf -font $uifont
pack .ctop.top.lbar.vhl -side left -fill y
@@ -1474,7 +1474,7 @@ proc doviewmenu {m first cmd op argv} {
proc allviewmenus {n op args} {
global viewhlmenu
doviewmenu .bar.view 7 [list showview $n] $op $args
doviewmenu .bar.view 5 [list showview $n] $op $args
doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
}
@@ -1516,7 +1516,7 @@ proc newviewok {top n} {
set viewperm($n) $newviewperm($n)
if {$newviewname($n) ne $viewname($n)} {
set viewname($n) $newviewname($n)
doviewmenu .bar.view 7 [list showview $n] \
doviewmenu .bar.view 5 [list showview $n] \
entryconf [list -label $viewname($n)]
doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
entryconf [list -label $viewname($n) -value $viewname($n)]
@@ -1632,8 +1632,8 @@ proc showview {n} {
set curview $n
set selectedview $n
.bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf 3 -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}]
if {![info exists viewdata($n)]} {
set pending_select $selid
@@ -4899,9 +4899,9 @@ proc rowmenu {x y id} {
} else {
set state normal
}
$rowctxmenu entryconfigure 0 -state $state
$rowctxmenu entryconfigure 1 -state $state
$rowctxmenu entryconfigure 2 -state $state
$rowctxmenu entryconfigure "Diff this*" -state $state
$rowctxmenu entryconfigure "Diff selected*" -state $state
$rowctxmenu entryconfigure "Make patch" -state $state
set rowmenuid $id
tk_popup $rowctxmenu $x $y
}
@@ -6305,8 +6305,8 @@ if {$cmdline_files ne {} || $revtreeargs ne {}} {
set viewargs(1) $revtreeargs
set viewperm(1) 0
addviewmenu 1
.bar.view entryconf 2 -state normal
.bar.view entryconf 3 -state normal
.bar.view entryconf Edit* -state normal
.bar.view entryconf Delete* -state normal
}
if {[info exists permviews]} {