* Re: [PATCH] gitweb: Sort projects with undefined ages last
From: Matthew Daley @ 2012-12-11 10:56 UTC (permalink / raw)
To: gitster; +Cc: git, Matthew Daley
In-Reply-To: <7vip8actz3.fsf@alter.siamese.dyndns.org>
On Mon, Dec 10, 2012 at 7:16 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Yeah, it could be argued that in a very minor corner case showing
> new and empty ones at the top might attract more attention to them,
> but new and empty ones can stay inactive, so this change would be an
> overall improvement for these two sites. An alternative could be to
> give the mtime of the git directory to the age field if there is no
> commits in the repository, to sink the empty and inactive ones to
> the bottom quickly while showing newly created ones at the top, but
> it shouldn't make any practical difference.
Agreed.
> Two observations:
>
> * This iterates over the same @$projlist twice with grep, with one
> "defined" and the other "!defined", which may risk these two
> complementary grep conditions to go out of sync (it also may
> affect performance but that is a lessor issue).
>
> An alternative may be to change the expression used inside sort()
> to treat an undef as if it were a very large value, something
> like:
>
> sort {
> defined $a->{$oi->{'key'}}
> ? (defined $b->{$oi->{'key'}}
> ? ($a->{$oi->{'key'}} <=> $b->{$oi->{'key'}})
> : -1)
> : (defined $b->{$oi->{'key'}} ? 1 : 0);
> }
>
> * This "sort undefs at the end is better than at the beginning" is
> good only for the "age" field, and we wouldn't know if we would
> add other keys for which it may be better to sort undef at the
> beginning. The order_info{} currently has only one field of the
> 'num' type, so this is not an immediate issue, but in order to
> future proof, it may make sense to rewrite the sort_projects_list
> function to map the order field name to a function given to sort,
> e.g.
>
> my %order_sort = (
> project => sub { $a->{'path'} cmp $b->{'path'} },
> descr => sub { $a->{'descr_long'} cmp $b->{'descr_long'} },
> owner => sub { $a->{'owner'} cmp $b->{'owner'} },
> age => sub { ... the num cmp with undef above ... },
> );
> if (!exists $order_sort{$order}) {
> return @$projlist;
> }
> return sort $order_sort{$order} @$projlist;
>
> I am not sure the second one is worth it, though.
I thought about both of those variants as well. What about this:
-- >8 --
Subject: [PATCH] gitweb: Sort projects with undefined ages last
Sorting gitweb's project list by age ('Last Change') currently shows
projects with undefined ages at the head of the list. This gives a less
useful result when there are a number of projects that are missing or
otherwise faulty and one is trying to see what projects have been
updated recently.
Fix by sorting these projects with undefined ages at the bottom of the
list when sorting by age.
Signed-off-by: Matthew Daley <mattjd@gmail.com>
---
gitweb/gitweb.perl | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 0f207f2..656b324 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5528,23 +5528,30 @@ sub fill_project_list_info {
sub sort_projects_list {
my ($projlist, $order) = @_;
- my @projects;
- my %order_info = (
- project => { key => 'path', type => 'str' },
- descr => { key => 'descr_long', type => 'str' },
- owner => { key => 'owner', type => 'str' },
- age => { key => 'age', type => 'num' }
- );
- my $oi = $order_info{$order};
- return @$projlist unless defined $oi;
- if ($oi->{'type'} eq 'str') {
- @projects = sort {$a->{$oi->{'key'}} cmp $b->{$oi->{'key'}}} @$projlist;
- } else {
- @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @$projlist;
+ sub order_str {
+ my $key = shift;
+ return sub { $a->{$key} cmp $b->{$key} };
}
- return @projects;
+ sub order_num_then_undef {
+ my $key = shift;
+ return sub {
+ defined $a->{$key} ?
+ (defined $b->{$key} ? $a->{$key} <=> $b->{$key} : -1) :
+ (defined $b->{$key} ? 1 : 0)
+ };
+ }
+
+ my %orderings = (
+ project => order_str('path'),
+ descr => order_str('descr_long'),
+ owner => order_str('owner'),
+ age => order_num_then_undef('age'),
+ );
+
+ my $ordering = $orderings{$order};
+ return defined $ordering ? sort $ordering @$projlist : @$projlist;
}
# returns a hash of categories, containing the list of project
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] git-clean: Display more accurate delete messages
From: Zoltan Klinger @ 2012-12-11 12:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Soren Brinkmann, git
In-Reply-To: <7v38zecrqc.fsf@alter.siamese.dyndns.org>
>> Use git clean --force --force to delete all untracked git repositories
>
> But I am not sure if this is ever sane. Especially the one that
> removes an embedded repository is suspicious. "git clean" should
> not ever touch it with or without --superforce or any other command.
My original intention with this patch was to provide more accurate
delete messages for the git-clean command when it's used with the
current set of command line options. I didn't know that --force
--force was so controversial.
The --force --force option has been around since v1.6.4.2. Commit
a0f4afbe introduced it. If the consensus is that it is not a sane
option to have let's remove it by all means. But I think it should be
done in a separate patch '[PATCH] git-clean: Never delete any embedded
git repository' or such.
> I do not think trying to remove something that cannot be removed due
> to filesystem permissions is sensible, either. We simply should treat
> such a case a grave error and have the user sort things out, instead
> of blindly attempt to "chmod" them ourselves (which may still fail).
But this is not how git-clean works with or without the --force
--force flag. The recursive delete does the right thing: it tries to
delete a file or directory, if that fails for whatever reason it will
report the error and move on. That's it. No "chmod" or any other
hackery at all. The --force --force flag only means "if during
recursion you encounter an embedded git directory that is not tracked
you are allowed to recurse into it and keep on deleting files and
sub-directories as per usual".
Cheers,
Zoltan
^ permalink raw reply
* How to avoid the ^M induced by Meld and Git
From: Karl Brand @ 2012-12-11 12:33 UTC (permalink / raw)
To: git
Esteemed Git users,
What i do:
1. Create a script.r using Emacs/ESS.
2. Make some modifications to script.r with the nice diff gui, Meld
3. Commit these modifications using git commit -am "my message"
4. Reopen script.r in Emacs/ESS to continue working.
The lines added (&/edited ?) using Meld all end with ^M which i
certainly don't want. Lines not added/edited with Meld do NOT end with ^M.
There are plenty of posts around about these being line endings used for
windows which can appear when working on a script under a *nix OS which
has previously been edited in a Windows OS. This is not the case here -
everything is taking place on Ubuntu 12.04.
FWIW: the directory is being synced by dropbox; and in Meld, Preferences
> Encoding tab, "utf8" is entered in the text box.
Current work around is running in a terminal: dos2unix /path/to/script.r
which strips the ^M's
But this just shouldn't be necessary and I'd really appreciate the
reflections & advice on how to stop inducing these ^M's !
With thanks,
Karl
(re)posted here as suggested off topic at SO:
http://stackoverflow.com/questions/13799631/create-script-r-in-emacs-modify-with-meld-git-commit-reopen-in-emacs-m
--
Karl Brand
Dept of Cardiology and Dept of Bioinformatics
Erasmus MC
Dr Molewaterplein 50
3015 GE Rotterdam
T +31 (0)10 703 2460 |M +31 (0)642 777 268 |F +31 (0)10 704 4161
^ permalink raw reply
* [BUG] Cannot push some grafted branches
From: Yann Dirson @ 2012-12-11 14:39 UTC (permalink / raw)
To: git list
There seems to be some bad interactions between git-push and grafts.
The problem seems to occur when a commit that exists in the remote
repo is subject to a graft in the local repo, and we try to push one
of the fake parents.
The problem was first seen on 1.7.12.3 in a private repo, and I could
reproduce it using 1.8.1.rc0, as shown below. 1.7.10.4 seems even
more affected, with something looking like a memory corruption issue.
Here is the test:
$ git clone git.git git-test
Cloning into 'git-test'...
done.
Checking out files: 100% (2518/2518), done.
$ cd git-test/
git-test$ git co maint
Branch maint set up to track remote branch maint from origin.
Switched to a new branch 'maint'
git-test$ echo >> README
git-test$ git commit -a -m "test"
[maint 0708279] test
1 file changed, 1 insertion(+)
git-test$ echo $(git rev-parse origin/master; git rev-parse origin/master^; git rev-parse HEAD) > .git/info/grafts
git-test$ git version
git version 1.8.1.rc0
git-test$ git push origin maint
Total 0 (delta 0), reused 0 (delta 0)
fatal: bad object 0708279e168b52003234dd23601796b3b12e278b
fatal: bad object 0708279e168b52003234dd23601796b3b12e278b
To /home/localadm/softs/git.git
! [remote rejected] maint -> maint (missing necessary objects)
error: failed to push some refs to '/home/localadm/softs/git.git'
$ git version
git version 1.7.10.4
git-test$ git push origin maint
Total 0 (delta 0), reused 0 (delta 0)
fatal: bad object 0708279e168b52003234dd23601796b3b12e278b
fatal: bad object 0708279e168b52003234dd23601796b3b12e278b
Auto packing the repository for optimum performance.
fatal: protocol error: bad line length character: Remo
error: error in sideband demultiplexer
error: >S��ŋJ�jB�;�x'��R died of signal 13
To /home/localadm/softs/git.git
! [remote rejected] maint -> maint (missing necessary objects)
error: failed to push some refs to '/home/localadm/softs/git.git'
--
Yann Dirson - Bertin Technologies
^ permalink raw reply
* Re: git-svn with non-standard repository layout
From: Piotr Krukowiecki @ 2012-12-11 15:46 UTC (permalink / raw)
To: Stephen Bash; +Cc: Git Mailing List, Carsten Fuchs
In-Reply-To: <516524996.289805.1354751683987.JavaMail.root@genarts.com>
On Thu, Dec 6, 2012 at 12:54 AM, Stephen Bash <bash@genarts.com> wrote:
> ----- Original Message -----
>> From: "Piotr Krukowiecki" <piotr.krukowiecki@gmail.com>
>> Sent: Wednesday, December 5, 2012 5:19:44 PM
>> Subject: Re: git-svn with non-standard repository layout
>>
>> Do you mean something like
>>
>> branches = branches/work/*/*:refs/remotes/work/*
>> branches = branches/{branch1,branch2}:refs/remotes/branches/*
>>
>> instead of (currently used)
>>
>> branches = branches/work/*/*:refs/remotes/work/*
>> fetch = branches/branch1:refs/remotes/branches/branch1
>> fetch = branches/branch2:refs/remotes/branches/branch2
>
> Essentially yes. But I guess since you have branches at the same level as the work directory,
> you either have to add to the glob for each new branch or add another fetch line... Doesn't seem
> like a big win to me. Jumping on a tangent, I thought there could only be one wildcard on the
> left side of the ':' (and the '*' on the right). If your work/*/* is actually working, that's quite interesting.
At first I though it was working, but it seems it does not. I have
several branches, including:
remotes/trunk
remotes/work/user/xxx (based on remotes/trunk)
master (based on remotes/trunk)
xxx (based on remotes/work/user/xxx)
If I do 'git svn rebase -l' on xxx, it rebases commits on xxx (i.e.
remotes/trunk..remotes/work/user/xxx)
on top of master, so now xxx is based on master :(
I don't know if this is git-svn bug, or the problem with 'work/*/*'
pattern, or something else...
I will try explicit branches specification and will see what happens.
--
Piotr Krukowiecki
^ permalink raw reply
* Re: [PATCH] gitweb: Sort projects with undefined ages last
From: Junio C Hamano @ 2012-12-11 18:08 UTC (permalink / raw)
To: Matthew Daley; +Cc: git
In-Reply-To: <1355223367-5894-1-git-send-email-mattjd@gmail.com>
Matthew Daley <mattjd@gmail.com> writes:
> I thought about both of those variants as well. What about this:
>
> -- >8 --
> Subject: [PATCH] gitweb: Sort projects with undefined ages last
>
> Sorting gitweb's project list by age ('Last Change') currently shows
> projects with undefined ages at the head of the list. This gives a less
> useful result when there are a number of projects that are missing or
> otherwise faulty and one is trying to see what projects have been
> updated recently.
>
> Fix by sorting these projects with undefined ages at the bottom of the
> list when sorting by age.
>
> Signed-off-by: Matthew Daley <mattjd@gmail.com>
> ---
Looks sensible to me. Thanks; will queue.
> gitweb/gitweb.perl | 35 +++++++++++++++++++++--------------
> 1 file changed, 21 insertions(+), 14 deletions(-)
>
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index 0f207f2..656b324 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -5528,23 +5528,30 @@ sub fill_project_list_info {
>
> sub sort_projects_list {
> my ($projlist, $order) = @_;
> - my @projects;
>
> - my %order_info = (
> - project => { key => 'path', type => 'str' },
> - descr => { key => 'descr_long', type => 'str' },
> - owner => { key => 'owner', type => 'str' },
> - age => { key => 'age', type => 'num' }
> - );
> - my $oi = $order_info{$order};
> - return @$projlist unless defined $oi;
> - if ($oi->{'type'} eq 'str') {
> - @projects = sort {$a->{$oi->{'key'}} cmp $b->{$oi->{'key'}}} @$projlist;
> - } else {
> - @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @$projlist;
> + sub order_str {
> + my $key = shift;
> + return sub { $a->{$key} cmp $b->{$key} };
> }
>
> - return @projects;
> + sub order_num_then_undef {
> + my $key = shift;
> + return sub {
> + defined $a->{$key} ?
> + (defined $b->{$key} ? $a->{$key} <=> $b->{$key} : -1) :
> + (defined $b->{$key} ? 1 : 0)
> + };
> + }
> +
> + my %orderings = (
> + project => order_str('path'),
> + descr => order_str('descr_long'),
> + owner => order_str('owner'),
> + age => order_num_then_undef('age'),
> + );
> +
> + my $ordering = $orderings{$order};
> + return defined $ordering ? sort $ordering @$projlist : @$projlist;
> }
>
> # returns a hash of categories, containing the list of project
^ permalink raw reply
* Re: [BUG] Cannot push some grafted branches
From: Junio C Hamano @ 2012-12-11 18:15 UTC (permalink / raw)
To: Yann Dirson; +Cc: git list
In-Reply-To: <20121211153903.7522d6b0@chalon.bertin.fr>
Yann Dirson <dirson@bertin.fr> writes:
> There seems to be some bad interactions between git-push and grafts.
> The problem seems to occur when a commit that exists in the remote
> repo is subject to a graft in the local repo, and we try to push one
> of the fake parents.
History tweaking by grafts is only visible inside your local
repository and objects are not rewritten, and grafts are not
transferred across repositories. They were invented to be used as a
stop-gap measure until you filter-branch the history before
publishing (or if you do not publish, then you can keep using your
local grafts).
Isn't this well known? Perhaps we would need to document it better.
What you can do is to use "replace" instead and publish the replace
refs, I think. Object transfer will then follow the true parenthood
connectivity and people who choose to use the same replacement as
you do can fetch the replace ref from you (this will grab objects
necessary to complete the alternative history) and install it.
^ permalink raw reply
* [PATCH v7 0/3] submodule update: add --remote for submodule's upstream changes
From: W. Trevor King @ 2012-12-11 18:58 UTC (permalink / raw)
To: Git
Cc: Junio C Hamano, Heiko Voigt, Jeff King, Phil Hord, Shawn Pearce,
Jens Lehmann, Nahor, W. Trevor King
In-Reply-To: <20121204001717.GA17375@odin.tremily.us>
From: "W. Trevor King" <wking@tremily.us>
I see that this series has dropped out of "what's cooking?".
Hopefully this reroll gets it back in ;).
Changes since v6 (both in response to Junio's comments):
* Fix style in get_submodule_config definition.
* Drop the submodule.<name>.remote config option (v6's patch 4).
W. Trevor King (3):
submodule: add get_submodule_config helper funtion
submodule update: add --remote for submodule's upstream changes
submodule add: If --branch is given, record it in .gitmodules
Documentation/config.txt | 7 +++++-
Documentation/git-submodule.txt | 27 ++++++++++++++++++++-
Documentation/gitmodules.txt | 5 ++++
git-submodule.sh | 52 ++++++++++++++++++++++++++++++++++++++++-
t/t7400-submodule-basic.sh | 1 +
t/t7406-submodule-update.sh | 31 ++++++++++++++++++++++++
6 files changed, 120 insertions(+), 3 deletions(-)
--
1.8.0
^ permalink raw reply
* [PATCH v7 1/3] submodule: add get_submodule_config helper funtion
From: W. Trevor King @ 2012-12-11 18:58 UTC (permalink / raw)
To: Git
Cc: Junio C Hamano, Heiko Voigt, Jeff King, Phil Hord, Shawn Pearce,
Jens Lehmann, Nahor, W. Trevor King
In-Reply-To: <cover.1355251862.git.wking@tremily.us>
From: "W. Trevor King" <wking@tremily.us>
Several submodule configuration variables
(e.g. fetchRecurseSubmodules) are read from .gitmodules with local
overrides from the usual git config files. This shell function mimics
that logic to help initialize configuration variables in
git-submodule.sh.
Signed-off-by: W. Trevor King <wking@tremily.us>
---
git-submodule.sh | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/git-submodule.sh b/git-submodule.sh
index ab6b110..f969f28 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -152,6 +152,32 @@ die_if_unmatched ()
}
#
+# Print a submodule configuration setting
+#
+# $1 = submodule name
+# $2 = option name
+# $3 = default value
+#
+# Checks in the usual git-config places first (for overrides),
+# otherwise it falls back on .gitmodules. This allows you to
+# distribute project-wide defaults in .gitmodules, while still
+# customizing individual repositories if necessary. If the option is
+# not in .gitmodules either, print a default value.
+#
+get_submodule_config () {
+ name="$1"
+ option="$2"
+ default="$3"
+ value=$(git config submodule."$name"."$option")
+ if test -z "$value"
+ then
+ value=$(git config -f .gitmodules submodule."$name"."$option")
+ fi
+ printf '%s' "${value:-$default}"
+}
+
+
+#
# Map submodule path to submodule name
#
# $1 = path
--
1.8.0
^ permalink raw reply related
* [PATCH v7 3/3] submodule add: If --branch is given, record it in .gitmodules
From: W. Trevor King @ 2012-12-11 18:58 UTC (permalink / raw)
To: Git
Cc: Junio C Hamano, Heiko Voigt, Jeff King, Phil Hord, Shawn Pearce,
Jens Lehmann, Nahor, W. Trevor King
In-Reply-To: <cover.1355251862.git.wking@tremily.us>
From: "W. Trevor King" <wking@tremily.us>
This allows you to easily record a submodule.<name>.branch option in
.gitmodules when you add a new submodule. With this patch,
$ git submodule add -b <branch> <repository> [<path>]
$ git config -f .gitmodules submodule.<path>.branch <branch>
reduces to
$ git submodule add -b <branch> <repository> [<path>]
This means that future calls to
$ git submodule update --remote ...
will get updates from the same branch that you used to initialize the
submodule, which is usually what you want.
Signed-off-by: W. Trevor King <wking@tremily.us>
---
Documentation/git-submodule.txt | 2 ++
git-submodule.sh | 4 ++++
t/t7400-submodule-basic.sh | 1 +
3 files changed, 7 insertions(+)
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 72dd52f..988bba9 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -208,6 +208,8 @@ OPTIONS
-b::
--branch::
Branch of repository to add as submodule.
+ The name of the branch is recorded as `submodule.<path>.branch` in
+ `.gitmodules` for `update --remote`.
-f::
--force::
diff --git a/git-submodule.sh b/git-submodule.sh
index 1395079..9f3f437 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -394,6 +394,10 @@ Use -f if you really want to add it." >&2
git config -f .gitmodules submodule."$sm_path".path "$sm_path" &&
git config -f .gitmodules submodule."$sm_path".url "$repo" &&
+ if test -n "$branch"
+ then
+ git config -f .gitmodules submodule."$sm_path".branch "$branch"
+ fi &&
git add --force .gitmodules ||
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
}
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 5397037..90e2915 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -133,6 +133,7 @@ test_expect_success 'submodule add --branch' '
(
cd addtest &&
git submodule add -b initial "$submodurl" submod-branch &&
+ test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
git submodule init
) &&
--
1.8.0
^ permalink raw reply related
* [PATCH v7 2/3] submodule update: add --remote for submodule's upstream changes
From: W. Trevor King @ 2012-12-11 18:58 UTC (permalink / raw)
To: Git
Cc: Junio C Hamano, Heiko Voigt, Jeff King, Phil Hord, Shawn Pearce,
Jens Lehmann, Nahor, W. Trevor King
In-Reply-To: <cover.1355251862.git.wking@tremily.us>
From: "W. Trevor King" <wking@tremily.us>
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
---
Documentation/config.txt | 7 ++++++-
Documentation/git-submodule.txt | 25 ++++++++++++++++++++++++-
Documentation/gitmodules.txt | 5 +++++
git-submodule.sh | 22 +++++++++++++++++++++-
t/t7406-submodule-update.sh | 31 +++++++++++++++++++++++++++++++
5 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 11f320b..6f4663c 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1998,7 +1998,12 @@ submodule.<name>.update::
for a submodule. These variables are initially populated
by 'git submodule init'; edit them to override the
URL and other values found in the `.gitmodules` file. See
- linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
+
+submodule.<name>.branch::
+ The remote branch name for a submodule, used by `git submodule
+ update --remote`. Set this option to override the value found in
+ the `.gitmodules` file. See linkgit:git-submodule[1] and
+ linkgit:gitmodules[5] for details.
submodule.<name>.fetchRecurseSubmodules::
This option can be used to control recursive fetching of this
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index b4683bb..72dd52f 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -13,7 +13,7 @@ SYNOPSIS
[--reference <repository>] [--] <repository> [<path>]
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
+'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [--rebase]
[--reference <repository>] [--merge] [--recursive] [--] [<path>...]
'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
[commit] [--] [<path>...]
@@ -236,6 +236,29 @@ OPTIONS
(the default). This limit only applies to modified submodules. The
size is always limited to 1 for added/deleted/typechanged submodules.
+--remote::
+ This option is only valid for the update command. Instead of using
+ the superproject's recorded SHA-1 to update the submodule, use the
+ status of the submodule's remote tracking branch. The remote used
+ is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
+ The remote branch used defaults to `master`, but the branch name may
+ be overridden by setting the `submodule.<name>.branch` option in
+ either `.gitmodules` or `.git/config` (with `.git/config` taking
+ precedence).
++
+This works for any of the supported update procedures (`--checkout`,
+`--rebase`, etc.). The only change is the source of the target SHA-1.
+For example, `submodule update --remote --merge` will merge upstream
+submodule changes into the submodules, while `submodule update
+--merge` will merge superproject gitlink changes into the submodules.
++
+In order to ensure a current tracking branch state, `update --remote`
+fetches the submodule's remote repository before calculating the
+SHA-1. This makes `submodule update --remote --merge` similar to
+running `git pull` in the submodule. If you don't want to fetch (for
+something closer to `git merge`), you should use `submodule update
+--remote --no-fetch --merge`.
+
-N::
--no-fetch::
This option is only valid for the update command.
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index 4effd78..4004fa6 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -47,6 +47,11 @@ submodule.<name>.update::
This config option is overridden if 'git submodule update' is given
the '--merge', '--rebase' or '--checkout' options.
+submodule.<name>.branch::
+ A remote branch name for tracking updates in the upstream submodule.
+ If the option is not specified, it defaults to 'master'. See the
+ `--remote` documentation in linkgit:git-submodule[1] for details.
+
submodule.<name>.fetchRecurseSubmodules::
This option can be used to control recursive fetching of this
submodule. If this option is also present in the submodules entry in
diff --git a/git-submodule.sh b/git-submodule.sh
index f969f28..1395079 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -8,7 +8,8 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: $dashless [--quiet] init [--] [<path>...]
- or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+ or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+ges
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command>
or: $dashless [--quiet] sync [--] [<path>...]"
@@ -26,6 +27,7 @@ cached=
recursive=
init=
files=
+remote=
nofetch=
update=
prefix=
@@ -535,6 +537,9 @@ cmd_update()
-i|--init)
init=1
;;
+ --remote)
+ remote=1
+ ;;
-N|--no-fetch)
nofetch=1
;;
@@ -595,6 +600,7 @@ cmd_update()
fi
name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url)
+ branch=$(get_submodule_config "$name" branch master)
if ! test -z "$update"
then
update_module=$update
@@ -629,6 +635,20 @@ Maybe you want to use 'update --init'?")"
die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
fi
+ if test -n "$remote"
+ then
+ if test -z "$nofetch"
+ then
+ # Fetch remote before determining tracking $sha1
+ (clear_local_git_env; cd "$sm_path" && git-fetch) ||
+ die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
+ fi
+ remote_name=$(get_default_remote)
+ sha1=$(clear_local_git_env; cd "$sm_path" &&
+ git rev-parse --verify "${remote_name}/${branch}") ||
+ die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
+ fi
+
if test "$subsha1" != "$sha1" -o -n "$force"
then
subforce=$force
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 1542653..a567834 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -135,6 +135,37 @@ test_expect_success 'submodule update --force forcibly checks out submodules' '
)
'
+test_expect_success 'submodule update --remote should fetch upstream changes' '
+ (cd submodule &&
+ echo line4 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line4"
+ ) &&
+ (cd super &&
+ git submodule update --remote --force submodule &&
+ cd submodule &&
+ test "$(git log -1 --oneline)" = "$(GIT_DIR=../../submodule/.git git log -1 --oneline)"
+ )
+'
+
+test_expect_success 'local config should override .gitmodules branch' '
+ (cd submodule &&
+ git checkout -b test-branch &&
+ echo line5 >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line5" &&
+ git checkout master
+ ) &&
+ (cd super &&
+ git config submodule.submodule.branch test-branch &&
+ git submodule update --remote --force submodule &&
+ cd submodule &&
+ test "$(git log -1 --oneline)" = "$(GIT_DIR=../../submodule/.git git log -1 --oneline test-branch)"
+ )
+'
+
test_expect_success 'submodule update --rebase staying on master' '
(cd super/submodule &&
git checkout master
--
1.8.0
^ permalink raw reply related
* [RFC/PATCH] ignoring a fetch that overwrites local symref
From: Junio C Hamano @ 2012-12-11 19:46 UTC (permalink / raw)
To: git; +Cc: Shawn O . Pearce, Jay Soffian, Stefan Zager
In-Reply-To: <1271714912-56659-1-git-send-email-jaysoffian@gmail.com>
This is a companion to an ancient thread
http://thread.gmane.org/gmane.comp.version-control.git/145311/focus=145337
in which an error was dealt with while pushing into a "mirror"
repository that has a symbolic reference refs/remotes/origin/HEAD
pointing at refs/remotes/origin/master with "git push --mirror".
The issue was that the receiving end was told to update origin/HEAD
and origin/master separately; if origin/HEAD is updated, that would
update origin/master at the same time, and then when attempting to
update origin/master, it would notice that it no longer has the
expected old value and barf. After the series, we started ignoring
such pushes to HEAD on the receiving end.
But you can suffer from a similar issue transferring objects in the
opposite direction. If you run "fetch --mirror" in to such a
"mirror" repository, the other side would advertise both 'master'
and 'HEAD' under refs/remotes/origin/ hierarchy, and refs/*:refs/*
wildcard would try to grab both of them.
Work it around by noticing a wildcard match that attempts to update
a local symbolic ref and ignoring it.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* While I do not think it is sane to have symbolic refs in the
receiving ref hierarchy (e.g. refs/remotes/origin/) that has a
matching ref in the corresponding ref hierarchy in the sending
side (e.g. the same, or refs/heads/ if you are doing a mirror) in
the first place, we addressed the issue brought by such a setting
on the push side, so it is probably a good idea to do it on the
fetch side.
This is marked RFC as it cheats by ignoring symrefs that were not
explicitly asked, instead of doing the "is the underlying thing
going to be updated with the same operation?" logic the old patch
did in da3efdb (receive-pack: detect aliased updates which can
occur with symrefs, 2010-04-19). I think this simpler logic is
sufficient but there may be corner cases that merit the more
elaborate one, hence RFC.
remote.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git i/remote.c w/remote.c
index 6aa49c0..ca1f8f2 100644
--- i/remote.c
+++ w/remote.c
@@ -1370,6 +1370,16 @@ int branch_merge_matches(struct branch *branch,
return refname_match(branch->merge[i]->src, refname, ref_fetch_rules);
}
+static int ignore_symref_update(const char *refname)
+{
+ unsigned char sha1[20];
+ int flag;
+
+ if (!resolve_ref_unsafe(refname, sha1, 0, &flag))
+ return 0; /* non-existing refs are OK */
+ return (flag & REF_ISSYMREF);
+}
+
static struct ref *get_expanded_map(const struct ref *remote_refs,
const struct refspec *refspec)
{
@@ -1383,7 +1393,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
if (strchr(ref->name, '^'))
continue; /* a dereference item */
if (match_name_with_pattern(refspec->src, ref->name,
- refspec->dst, &expn_name)) {
+ refspec->dst, &expn_name) &&
+ !ignore_symref_update(expn_name)) {
struct ref *cpy = copy_ref(ref);
cpy->peer_ref = alloc_ref(expn_name);
^ permalink raw reply related
* [PATCH] nedmalloc: Fix a compile warning (exposed as error) with GCC 4.7.2
From: Sebastian Schuberth @ 2012-12-11 20:34 UTC (permalink / raw)
To: git
On MinGW, GCC 4.7.2 complains about
operation on 'p->m[end]' may be undefined
Fix this by replacing the faulty lines with those of 69825ca from
https://github.com/ned14/nedmalloc/blob/master/nedmalloc.c
Signed-off-by: Sebastian Schuberth <sschuberth@gmail.com>
---
compat/nedmalloc/nedmalloc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c
index d9a17a8..91c4e7f 100644
--- a/compat/nedmalloc/nedmalloc.c
+++ b/compat/nedmalloc/nedmalloc.c
@@ -603,7 +603,10 @@ static NOINLINE mstate FindMSpace(nedpool *p, threadcache *tc, int *lastUsed, si
}
/* We really want to make sure this goes into memory now but we
have to be careful of breaking aliasing rules, so write it twice */
- *((volatile struct malloc_state **) &p->m[end])=p->m[end]=temp;
+ {
+ volatile struct malloc_state **_m=(volatile struct malloc_state **) &p->m[end];
+ *_m=(p->m[end]=temp);
+ }
ACQUIRE_LOCK(&p->m[end]->mutex);
/*printf("Created mspace idx %d\n", end);*/
RELEASE_LOCK(&p->mutex);
--
1.8.0.msysgit.1
^ permalink raw reply related
* (bug?) Inconsistent workdir file timestamps after initial clone.
From: Marc Branchaud @ 2012-12-11 20:52 UTC (permalink / raw)
To: Git Mailing List
Hi all,
Occasionally when doing a fresh clone of a repo, if the clock ticks at just
the wrong time the checked-out files end up with different timestamps.
The effect of this can be that, when "make" is run in the workdir it'll
decide that some files are out of date and try to rebuild them.
(In our particular case, our automated build-bot cloned a submodule of some
third-party (i.e. not our) code, where a Makefile.in got an earlier timestamp
than its dependent Makefile.am, so "configure && make" then tried to rebuild
Makefile.in and the build failed because our build environment has the wrong
version of automake.)
I'm completely unfamiliar with the clone-and-checkout parts of git's code, so
my first question really is if someone more familiar with the code could look
at it (or at least point me to it) to verify whether or not such inconsistent
timestamps are possible.
If someone can please confirm that timestamps will always be consistent on
the initial checkout of a clone, then I'll have to hunt for a different cause
of our build failure.
However, if inconsistent timestamps are possible, I'd like to suggest that
this should be fixed. (I'd learn the code and write a patch myself, but as
some of you may know I haven't had very much time for git hacking lately.)
Thanks!
M.
^ permalink raw reply
* Re: (bug?) Inconsistent workdir file timestamps after initial clone.
From: Junio C Hamano @ 2012-12-11 21:27 UTC (permalink / raw)
To: Marc Branchaud; +Cc: Git Mailing List
In-Reply-To: <50C79D1F.1080709@xiplink.com>
Marc Branchaud <marcnarc@xiplink.com> writes:
> Occasionally when doing a fresh clone of a repo, if the clock ticks at just
> the wrong time the checked-out files end up with different timestamps.
>
> The effect of this can be that, when "make" is run in the workdir it'll
> decide that some files are out of date and try to rebuild them.
>
> (In our particular case, our automated build-bot cloned a submodule of some
> third-party (i.e. not our) code, where a Makefile.in got an earlier timestamp
> than its dependent Makefile.am, so "configure && make" then tried to rebuild
> Makefile.in and the build failed because our build environment has the wrong
> version of automake.)
Even if you somehow arrange Makefile.in and Makefile.am to have the
same timestamp, wouldn't it be up to your "make" to decide which one
is newer? Certainly Makefile.in is not newer than Makefile.am, and
it is free to try rebuilding it.
Also if you do this after any operation:
$ rm Makefile.am
$ git checkout Makefile.am
you will have Makefile.am that is newer than your Makefile.in and
you will end up attempting to rebuild it.
The timestamp of a working tree file records the time at which it
was created in your working tree. It does not have any relation to
the commit or author timestamp of the commit you check it out of.
If this command:
$ git checkout @{1.dacade.ago} Makefile.am
gave your Makefile.am an ancient timestamp, it will break your
build.
While not including files that can be rebuilt from the source may be
the ideal solution, I've seen projects hide rules to rebuild such a
"generated but needs special tools to build" and/or a "generated but
normal developers do not have any business rebuilding" file (in your
case, Makefile.in) in their Makefiles from the normal targets (like
"make all") for this exact reason, when they choose to distribute
such files by including in their commits.
^ permalink raw reply
* [PATCH] Add file completion to tcsh git completion.
From: Marc Khouzam @ 2012-12-11 21:36 UTC (permalink / raw)
To: 'git@vger.kernel.org'
Cc: 'felipe.contreras@gmail.com', 'szeder@ira.uka.de'
For bash completion, the option '-o bashdefault' is used to indicate
that when no other choices are available, file completion should be
performed. Since this option is not available in tcsh, no file
completion is ever performed. Therefore, commands like 'git add ',
'git send-email ', etc, require the user to manually type out
the file name. This can be quite annoying.
To improve the user experience we try to simulate file completion
directly in this script (although not perfectly).
The known issues with the file completion simulation are:
- Possible completions are shown with their directory prefix.
- Completions containing shell variables are not handled.
- Completions with ~ as the first character are not handled.
Signed-off-by: Marc Khouzam <marc.khouzam@ericsson.com>
---
Beyond the described fix, this commit also improves minor aspects
of the script. Normally I would submit these things in different
commits, but I felt it would be wasting the reviewers/maintainer
time as they are very minor. If you do prefer different commits,
just let me know. The minor improvements are:
- update header to recommend setting a tcsh variable
- all missing tabs have been added
- use ',' instead of '/' in 'complete' command for users that
prefer to hard-code the path which also contains a '/' and
would cause a conflict.
- unset a variable to avoid polluting the user's env.
Thanks
Marc
contrib/completion/git-completion.tcsh | 69 ++++++++++++++++++++++++++--------
1 file changed, 54 insertions(+), 15 deletions(-)
diff --git a/contrib/completion/git-completion.tcsh b/contrib/completion/git-completion.tcsh
index 471f47b..8aafb63 100644
--- a/contrib/completion/git-completion.tcsh
+++ b/contrib/completion/git-completion.tcsh
@@ -19,23 +19,26 @@
# (e.g. ~/.git-completion.tcsh and ~/.git-completion.bash).
# 2) Add the following line to your .tcshrc/.cshrc:
# source ~/.git-completion.tcsh
+# 3) For completion similar to bash, it is recommended to also
+# add the following line to your .tcshrc/.cshrc:
+# set autolist=ambiguous
+# It will tell tcsh to list the possible completion choices.
set __git_tcsh_completion_original_script = ${HOME}/.git-completion.bash
set __git_tcsh_completion_script = ${HOME}/.git-completion.tcsh.bash
# Check that the user put the script in the right place
if ( ! -e ${__git_tcsh_completion_original_script} ) then
- echo "git-completion.tcsh: Cannot find: ${__git_tcsh_completion_original_script}. Git completion will not work."
- exit
+ echo "git-completion.tcsh: Cannot find: ${__git_tcsh_completion_original_script}. Git completion will not work."
+ exit
endif
cat << EOF > ${__git_tcsh_completion_script}
#!bash
#
# This script is GENERATED and will be overwritten automatically.
-# Do not modify it directly. Instead, modify the git-completion.tcsh
-# script provided by Git core.
-#
+# Do not modify it directly. Instead, modify git-completion.tcsh
+# and source it again.
source ${__git_tcsh_completion_original_script}
@@ -47,22 +50,58 @@ COMP_WORDS=(\$2)
# tell us that the previous word is complete and the cursor
# is on the next word.
if [ "\${2: -1}" == " " ]; then
- # The last character is a space, so our location is at the end
- # of the command-line array
- COMP_CWORD=\${#COMP_WORDS[@]}
+ # The last character is a space, so our location is at the end
+ # of the command-line array
+ COMP_CWORD=\${#COMP_WORDS[@]}
else
- # The last character is not a space, so our location is on the
- # last word of the command-line array, so we must decrement the
- # count by 1
- COMP_CWORD=\$((\${#COMP_WORDS[@]}-1))
+ # The last character is not a space, so our location is on the
+ # last word of the command-line array, so we must decrement the
+ # count by 1
+ COMP_CWORD=\$((\${#COMP_WORDS[@]}-1))
fi
# Call _git() or _gitk() of the bash script, based on the first argument
_\${1}
IFS=\$'\n'
-echo "\${COMPREPLY[*]}" | sort | uniq
+if [ \${#COMPREPLY[*]} -gt 0 ]; then
+ echo "\${COMPREPLY[*]}" | sort | uniq
+else
+ # No completions suggested. In this case, we want tcsh to perform
+ # standard file completion. However, there does not seem to be way
+ # to tell tcsh to do that. To help the user, we try to simulate
+ # file completion directly in this script.
+ #
+ # Known issues:
+ # - Possible completions are shown with their directory prefix.
+ # - Completions containing shell variables are not handled.
+ # - Completions with ~ as the first character are not handled.
+
+ # No file completion should be done unless we are completing beyond
+ # the git sub-command. An improvement on the bash completion :)
+ if [ \${COMP_CWORD} -gt 1 ]; then
+ TO_COMPLETE="\${COMP_WORDS[\${COMP_CWORD}]}"
+
+ # We don't support ~ expansion: too tricky.
+ if [ "\${TO_COMPLETE:0:1}" != "~" ]; then
+ # Use ls so as to add the '/' at the end of directories.
+ RESULT=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
+ echo \${RESULT[*]}
+
+ # If there is a single completion and it is a directory,
+ # we output it a second time to trick tcsh into not adding a space
+ # after it.
+ if [ \${#RESULT[*]} -eq 1 ] && [ "\${RESULT[0]: -1}" == "/" ]; then
+ echo \${RESULT[*]}
+ fi
+ fi
+ fi
+fi
+
EOF
-complete git 'p/*/`bash ${__git_tcsh_completion_script} git "${COMMAND_LINE}"`/'
-complete gitk 'p/*/`bash ${__git_tcsh_completion_script} gitk "${COMMAND_LINE}"`/'
+# Don't need this variable anymore, so don't pollute the users environment
+unset __git_tcsh_completion_original_script
+
+complete git 'p,*,`bash ${__git_tcsh_completion_script} git "${COMMAND_LINE}"`,'
+complete gitk 'p,*,`bash ${__git_tcsh_completion_script} gitk "${COMMAND_LINE}"`,'
--
1.8.0.1.g9fe2839
^ permalink raw reply related
* Re: (bug?) Inconsistent workdir file timestamps after initial clone.
From: Marc Branchaud @ 2012-12-11 22:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vy5h47003.fsf@alter.siamese.dyndns.org>
On 12-12-11 04:27 PM, Junio C Hamano wrote:
> Marc Branchaud <marcnarc@xiplink.com> writes:
>
>> Occasionally when doing a fresh clone of a repo, if the clock ticks at just
>> the wrong time the checked-out files end up with different timestamps.
>>
>> The effect of this can be that, when "make" is run in the workdir it'll
>> decide that some files are out of date and try to rebuild them.
>>
>> (In our particular case, our automated build-bot cloned a submodule of some
>> third-party (i.e. not our) code, where a Makefile.in got an earlier timestamp
>> than its dependent Makefile.am, so "configure && make" then tried to rebuild
>> Makefile.in and the build failed because our build environment has the wrong
>> version of automake.)
>
> Even if you somehow arrange Makefile.in and Makefile.am to have the
> same timestamp, wouldn't it be up to your "make" to decide which one
> is newer? Certainly Makefile.in is not newer than Makefile.am, and
> it is free to try rebuilding it.
Well, the makes I've used don't rebuild anything after a "touch *". I think
it would surprise a lot of people if their make did rebuild files when their
timestamps matched.
> Also if you do this after any operation:
>
> $ rm Makefile.am
> $ git checkout Makefile.am
>
> you will have Makefile.am that is newer than your Makefile.in and
> you will end up attempting to rebuild it.
Yes, of course. I would never expect otherwise.
> The timestamp of a working tree file records the time at which it
> was created in your working tree. It does not have any relation to
> the commit or author timestamp of the commit you check it out of.
> If this command:
>
> $ git checkout @{1.dacade.ago} Makefile.am
>
> gave your Makefile.am an ancient timestamp, it will break your
> build.
Yes, I agree.
My point is that the initial checkout into an empty working directory should
create all files with the same timestamp.
Or, to be a bit more precise, whenever git-checkout *creates* files in the
work dir, *all* the created files should have the *same* timestamp (i.e. the
current time measured at the start of the checkout's execution, not some
bizarro other time specified by some arcane heuristic).
The more I think about it, the more I think it's sloppy for git-checkout to
just let the filesystem assign the exact current time to created files. A
checkout theoretically should be atomic -- you really shouldn't try to play
with any of the files in your workdir while a checkout is underway. It's
impractical to really make checkouts atomic, but I think the end result of a
checkout should as much as possible look like the checkout happened all at
one time.
> While not including files that can be rebuilt from the source may be
> the ideal solution, I've seen projects hide rules to rebuild such a
> "generated but needs special tools to build" and/or a "generated but
> normal developers do not have any business rebuilding" file (in your
> case, Makefile.in) in their Makefiles from the normal targets (like
> "make all") for this exact reason, when they choose to distribute
> such files by including in their commits.
I prefer to use the third-party code as-is, without hacking it, to have
smooth upgrades in the future.
M.
^ permalink raw reply
* [PATCH 0/5] Allow git log to use mailmap file
From: Antoine Pelisse @ 2012-12-11 22:21 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Rich Midwinter, Antoine Pelisse
Implement the feature suggested here [1] by Rich Mindwinter
and Junio C Hamano (and following his advices)
This is a pre-version so there are a bunch of things still missing,
among them:
- There is no tests
- Grep search for mailmap author/committer is not available
- There is no documentation of the new option
[1]: http://thread.gmane.org/gmane.comp.version-control.git/211270
Antoine Pelisse (5):
Use split_ident_line to parse author and committer
mailmap: Remove buffer length limit in map_user
mailmap: Add mailmap structure to rev_info and pp
pretty: Use mailmap to display username and email
log: Add --use-mailmap option
builtin/blame.c | 59 +++++++++++++++++-------------------------------
builtin/log.c | 9 +++++++-
commit.h | 1 +
log-tree.c | 1 +
mailmap.c | 16 ++++++-------
pretty.c | 70 ++++++++++++++++++++++++++++++++++++---------------------
revision.h | 1 +
7 files changed, 84 insertions(+), 73 deletions(-)
--
1.8.1.rc1.5.g7e0651a
^ permalink raw reply
* [PATCH 2/5] mailmap: Remove buffer length limit in map_user
From: Antoine Pelisse @ 2012-12-11 22:21 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Rich Midwinter, Antoine Pelisse
In-Reply-To: <1355264493-8298-1-git-send-email-apelisse@gmail.com>
Remove the hard limit set by mail buffer in map_user and
use the strbuf API to replace it.
Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
mailmap.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/mailmap.c b/mailmap.c
index ea4b471..e636278 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -193,7 +193,8 @@ int map_user(struct string_list *map,
char *end_of_email;
struct string_list_item *item;
struct mailmap_entry *me;
- char buf[1024], *mailbuf;
+ struct strbuf buf = STRBUF_INIT;
+ char *mailbuf;
int i;
/* figure out space requirement for email */
@@ -204,15 +205,13 @@ int map_user(struct string_list *map,
if (!end_of_email)
return 0;
}
- if (end_of_email - email + 1 < sizeof(buf))
- mailbuf = buf;
- else
- mailbuf = xmalloc(end_of_email - email + 1);
/* downcase the email address */
+ strbuf_grow(&buf, end_of_email - email);
for (i = 0; i < end_of_email - email; i++)
- mailbuf[i] = tolower(email[i]);
- mailbuf[i] = 0;
+ strbuf_addch(&buf, tolower(email[i]));
+ strbuf_addch(&buf, 0);
+ mailbuf = strbuf_detach(&buf, 0);
debug_mm("map_user: map '%s' <%s>\n", name, mailbuf);
item = string_list_lookup(map, mailbuf);
@@ -226,8 +225,7 @@ int map_user(struct string_list *map,
item = subitem;
}
}
- if (mailbuf != buf)
- free(mailbuf);
+ free(mailbuf);
if (item != NULL) {
struct mailmap_info *mi = (struct mailmap_info *)item->util;
if (mi->name == NULL && (mi->email == NULL || maxlen_email == 0)) {
--
1.8.1.rc1.5.g7e0651a
^ permalink raw reply related
* [PATCH 1/5] Use split_ident_line to parse author and committer
From: Antoine Pelisse @ 2012-12-11 22:21 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Rich Midwinter, Antoine Pelisse
In-Reply-To: <1355264493-8298-1-git-send-email-apelisse@gmail.com>
Currently blame.c::get_acline and pretty.c::pp_user_info()
are parsing author name, email, time and tz themselves.
Use ident.c::split_ident_line for better code reuse.
Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
builtin/blame.c | 59 ++++++++++++++++++++-------------------------------------
pretty.c | 32 +++++++++++++++++--------------
2 files changed, 39 insertions(+), 52 deletions(-)
diff --git a/builtin/blame.c b/builtin/blame.c
index cfae569..dd4aff9 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1343,8 +1343,9 @@ static void get_ac_line(const char *inbuf, const char *what,
int mail_len, char *mail,
unsigned long *time, const char **tz)
{
- int len, tzlen, maillen;
- char *tmp, *endp, *timepos, *mailpos;
+ struct ident_split ident;
+ int len, tzlen, maillen, namelen;
+ char *tmp, *endp, *mailpos;
tmp = strstr(inbuf, what);
if (!tmp)
@@ -1355,7 +1356,10 @@ static void get_ac_line(const char *inbuf, const char *what,
len = strlen(tmp);
else
len = endp - tmp;
- if (person_len <= len) {
+ if (person_len <= len)
+ goto error_out;
+
+ if (split_ident_line(&ident, tmp, len)) {
error_out:
/* Ugh */
*tz = "(unknown)";
@@ -1364,47 +1368,26 @@ static void get_ac_line(const char *inbuf, const char *what,
*time = 0;
return;
}
- memcpy(person, tmp, len);
- tmp = person;
- tmp += len;
- *tmp = 0;
- while (person < tmp && *tmp != ' ')
- tmp--;
- if (tmp <= person)
- goto error_out;
- *tz = tmp+1;
- tzlen = (person+len)-(tmp+1);
+ namelen = ident.name_end - ident.name_begin;
+ memcpy(person, ident.name_begin, namelen);
+ person[namelen] = 0;
- *tmp = 0;
- while (person < tmp && *tmp != ' ')
- tmp--;
- if (tmp <= person)
- goto error_out;
- *time = strtoul(tmp, NULL, 10);
- timepos = tmp;
+ maillen = ident.mail_end - ident.mail_begin + 2;
+ memcpy(mail, ident.mail_begin - 1, maillen);
+ mail[maillen] = 0;
- *tmp = 0;
- while (person < tmp && !(*tmp == ' ' && tmp[1] == '<'))
- tmp--;
- if (tmp <= person)
- return;
- mailpos = tmp + 1;
- *tmp = 0;
- maillen = timepos - tmp;
- memcpy(mail, mailpos, maillen);
+ *time = strtoul(ident.date_begin, NULL, 10);
- if (!mailmap.nr)
- return;
+ tzlen = ident.tz_end - ident.tz_begin;
- /*
- * mailmap expansion may make the name longer.
- * make room by pushing stuff down.
- */
- tmp = person + person_len - (tzlen + 1);
- memmove(tmp, *tz, tzlen);
+ /* Place tz at the end of person */
+ *tz = tmp = person + person_len - (tzlen + 1);
+ memcpy(tmp, ident.tz_begin, tzlen);
tmp[tzlen] = 0;
- *tz = tmp;
+
+ if (!mailmap.nr)
+ return;
/*
* Now, convert both name and e-mail using mailmap
diff --git a/pretty.c b/pretty.c
index 5bdc2e7..6730add 100644
--- a/pretty.c
+++ b/pretty.c
@@ -387,29 +387,33 @@ void pp_user_info(const struct pretty_print_context *pp,
const char *what, struct strbuf *sb,
const char *line, const char *encoding)
{
+ struct ident_split ident;
+ int linelen, namelen;
+ char *line_end, *date;
int max_length = 78; /* per rfc2822 */
- char *date;
- int namelen;
unsigned long time;
int tz;
if (pp->fmt == CMIT_FMT_ONELINE)
return;
- date = strchr(line, '>');
- if (!date)
+
+ line_end = strchr(line, '\n');
+ if (!line_end)
+ return;
+
+ linelen = ++line_end - line;
+ if (split_ident_line(&ident, line, linelen))
return;
- namelen = ++date - line;
- time = strtoul(date, &date, 10);
+
+ namelen = ident.mail_end - ident.name_begin + 1;
+ time = strtoul(ident.date_begin, &date, 10);
tz = strtol(date, NULL, 10);
if (pp->fmt == CMIT_FMT_EMAIL) {
- char *name_tail = strchr(line, '<');
int display_name_length;
- if (!name_tail)
- return;
- while (line < name_tail && isspace(name_tail[-1]))
- name_tail--;
- display_name_length = name_tail - line;
+
+ display_name_length = ident.name_end - ident.name_begin;
+
strbuf_addstr(sb, "From: ");
if (needs_rfc2047_encoding(line, display_name_length, RFC2047_ADDRESS)) {
add_rfc2047(sb, line, display_name_length,
@@ -427,10 +431,10 @@ void pp_user_info(const struct pretty_print_context *pp,
}
if (namelen - display_name_length + last_line_length(sb) > max_length) {
strbuf_addch(sb, '\n');
- if (!isspace(name_tail[0]))
+ if (!isspace(ident.name_end[0]))
strbuf_addch(sb, ' ');
}
- strbuf_add(sb, name_tail, namelen - display_name_length);
+ strbuf_add(sb, ident.name_end, namelen - display_name_length);
strbuf_addch(sb, '\n');
} else {
strbuf_addf(sb, "%s: %.*s%.*s\n", what,
--
1.8.1.rc1.5.g7e0651a
^ permalink raw reply related
* [PATCH 3/5] mailmap: Add mailmap structure to rev_info and pp
From: Antoine Pelisse @ 2012-12-11 22:21 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Rich Midwinter, Antoine Pelisse
In-Reply-To: <1355264493-8298-1-git-send-email-apelisse@gmail.com>
the mailmap string_list structure filled with mailmap
information is passed along from rev_info to pretty_print_context
to provide mailmap information to pretty print each commits
with the correct username and email.
Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
commit.h | 1 +
log-tree.c | 1 +
revision.h | 1 +
3 files changed, 3 insertions(+)
diff --git a/commit.h b/commit.h
index b6ad8f3..7f8f987 100644
--- a/commit.h
+++ b/commit.h
@@ -89,6 +89,7 @@ struct pretty_print_context {
char *notes_message;
struct reflog_walk_info *reflog_info;
const char *output_encoding;
+ struct string_list *mailmap;
};
struct userformat_want {
diff --git a/log-tree.c b/log-tree.c
index 4f86def..92254fd 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -671,6 +671,7 @@ void show_log(struct rev_info *opt)
ctx.preserve_subject = opt->preserve_subject;
ctx.reflog_info = opt->reflog_info;
ctx.fmt = opt->commit_format;
+ ctx.mailmap = opt->mailmap;
pretty_print_commit(&ctx, commit, &msgbuf);
if (opt->add_signoff)
diff --git a/revision.h b/revision.h
index 059bfff..83a79f5 100644
--- a/revision.h
+++ b/revision.h
@@ -143,6 +143,7 @@ struct rev_info {
const char *subject_prefix;
int no_inline;
int show_log_size;
+ struct string_list *mailmap;
/* Filter by commit log message */
struct grep_opt grep_filter;
--
1.8.1.rc1.5.g7e0651a
^ permalink raw reply related
* [PATCH 4/5] pretty: Use mailmap to display username and email
From: Antoine Pelisse @ 2012-12-11 22:21 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Rich Midwinter, Antoine Pelisse
In-Reply-To: <1355264493-8298-1-git-send-email-apelisse@gmail.com>
Use the mailmap information to display the correct
username and email address in all log commands.
Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
pretty.c | 46 +++++++++++++++++++++++++++++++---------------
1 file changed, 31 insertions(+), 15 deletions(-)
diff --git a/pretty.c b/pretty.c
index 6730add..e232aaa 100644
--- a/pretty.c
+++ b/pretty.c
@@ -387,6 +387,8 @@ void pp_user_info(const struct pretty_print_context *pp,
const char *what, struct strbuf *sb,
const char *line, const char *encoding)
{
+ char person_name[1024];
+ char person_mail[1024];
struct ident_split ident;
int linelen, namelen;
char *line_end, *date;
@@ -405,41 +407,55 @@ void pp_user_info(const struct pretty_print_context *pp,
if (split_ident_line(&ident, line, linelen))
return;
- namelen = ident.mail_end - ident.name_begin + 1;
+ memcpy(person_mail, ident.mail_begin, ident.mail_end - ident.mail_begin);
+ person_mail[ident.mail_end - ident.mail_begin] = 0;
+
+ memcpy(person_name, ident.name_begin, ident.name_end - ident.name_begin);
+ person_name[ident.name_end - ident.name_begin] = 0;
+
+ if (pp->mailmap)
+ map_user(pp->mailmap, person_mail, sizeof(person_mail),
+ person_name, sizeof(person_name));
+
+ namelen = strlen(person_name) + strlen(person_mail);
time = strtoul(ident.date_begin, &date, 10);
tz = strtol(date, NULL, 10);
if (pp->fmt == CMIT_FMT_EMAIL) {
int display_name_length;
- display_name_length = ident.name_end - ident.name_begin;
+ display_name_length = strlen(person_name);
strbuf_addstr(sb, "From: ");
- if (needs_rfc2047_encoding(line, display_name_length, RFC2047_ADDRESS)) {
- add_rfc2047(sb, line, display_name_length,
+ if (needs_rfc2047_encoding(person_name, display_name_length, RFC2047_ADDRESS)) {
+ add_rfc2047(sb, person_name, display_name_length,
encoding, RFC2047_ADDRESS);
max_length = 76; /* per rfc2047 */
- } else if (needs_rfc822_quoting(line, display_name_length)) {
+ } else if (needs_rfc822_quoting(person_name,
+ display_name_length)) {
struct strbuf quoted = STRBUF_INIT;
- add_rfc822_quoted("ed, line, display_name_length);
+ add_rfc822_quoted("ed, person_name,
+ display_name_length);
strbuf_add_wrapped_bytes(sb, quoted.buf, quoted.len,
-6, 1, max_length);
strbuf_release("ed);
} else {
- strbuf_add_wrapped_bytes(sb, line, display_name_length,
- -6, 1, max_length);
+ strbuf_add_wrapped_bytes(sb, person_name,
+ display_name_length,
+ -6, 1, max_length);
}
- if (namelen - display_name_length + last_line_length(sb) > max_length) {
+ if (namelen - display_name_length + last_line_length(sb) > max_length)
strbuf_addch(sb, '\n');
- if (!isspace(ident.name_end[0]))
- strbuf_addch(sb, ' ');
- }
- strbuf_add(sb, ident.name_end, namelen - display_name_length);
+
+ strbuf_addch(sb, ' ');
+ strbuf_addch(sb, '<');
+ strbuf_add(sb, person_mail, strlen(person_mail));
+ strbuf_addch(sb, '>');
strbuf_addch(sb, '\n');
} else {
- strbuf_addf(sb, "%s: %.*s%.*s\n", what,
+ strbuf_addf(sb, "%s: %.*s%s <%s>\n", what,
(pp->fmt == CMIT_FMT_FULLER) ? 4 : 0,
- " ", namelen, line);
+ " ", person_name, person_mail);
}
switch (pp->fmt) {
case CMIT_FMT_MEDIUM:
--
1.8.1.rc1.5.g7e0651a
^ permalink raw reply related
* [PATCH 5/5] log: Add --use-mailmap option
From: Antoine Pelisse @ 2012-12-11 22:21 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Rich Midwinter, Antoine Pelisse
In-Reply-To: <1355264493-8298-1-git-send-email-apelisse@gmail.com>
Add the --use-mailmap option to log commands. It allows
to display names from mailmap file when displaying logs,
whatever the format used.
Signed-off-by: Antoine Pelisse <apelisse@gmail.com>
---
builtin/log.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/builtin/log.c b/builtin/log.c
index e7b7db1..d2bd8ce 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -22,6 +22,7 @@
#include "branch.h"
#include "streaming.h"
#include "version.h"
+#include "mailmap.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -94,11 +95,12 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
struct rev_info *rev, struct setup_revision_opt *opt)
{
struct userformat_want w;
- int quiet = 0, source = 0;
+ int quiet = 0, source = 0, mailmap = 0;
const struct option builtin_log_options[] = {
OPT_BOOLEAN(0, "quiet", &quiet, N_("suppress diff output")),
OPT_BOOLEAN(0, "source", &source, N_("show source")),
+ OPT_BOOLEAN(0, "use-mailmap", &mailmap, N_("Use mail map file")),
{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
PARSE_OPT_OPTARG, decorate_callback},
OPT_END()
@@ -136,6 +138,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
if (source)
rev->show_source = 1;
+ if (mailmap) {
+ rev->mailmap = xcalloc(1, sizeof(struct string_list));
+ read_mailmap(rev->mailmap, NULL);
+ }
+
if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
/*
* "log --pretty=raw" is special; ignore UI oriented
--
1.8.1.rc1.5.g7e0651a
^ permalink raw reply related
* Re: (bug?) Inconsistent workdir file timestamps after initial clone.
From: Junio C Hamano @ 2012-12-11 22:30 UTC (permalink / raw)
To: Marc Branchaud; +Cc: Git Mailing List
In-Reply-To: <50C7AE84.2060400@xiplink.com>
Marc Branchaud <marcnarc@xiplink.com> writes:
> My point is that the initial checkout into an empty working directory should
> create all files with the same timestamp.
>
> Or, to be a bit more precise, whenever git-checkout *creates* files in the
> work dir, *all* the created files should have the *same* timestamp (i.e. the
> current time measured at the start of the checkout's execution, not some
> bizarro other time specified by some arcane heuristic).
My knee-jerk reaction is that it is insane to do so, but what other
SCM does such a thing? Even "tar xf" wouldn't do that, I think.
>> While not including files that can be rebuilt from the source may be
>> the ideal solution, I've seen projects hide rules to rebuild such a
>> "generated but needs special tools to build" and/or a "generated but
>> normal developers do not have any business rebuilding" file (in your
>> case, Makefile.in) in their Makefiles from the normal targets (like
>> "make all") for this exact reason, when they choose to distribute
>> such files by including in their commits.
>
> I prefer to use the third-party code as-is, without hacking it, to have
> smooth upgrades in the future.
Then perhaps take the complaints to that third-party upstream, not
here?
^ permalink raw reply
* [PATCH] fetch: ignore wildcarded refspecs that update local symbolic refs
From: Junio C Hamano @ 2012-12-11 22:32 UTC (permalink / raw)
To: git; +Cc: Shawn O . Pearce, Jay Soffian, Stefan Zager
In-Reply-To: <7v62488j8a.fsf_-_@alter.siamese.dyndns.org>
In a repository cloned from somewhere else, you typically have a
symbolic ref refs/remotes/origin/HEAD pointing at the 'master'
remote-tracking ref that is next to it. When fetching into such a
repository with "git fetch --mirror" from another repository that
was similarly cloned, the implied wildcard refspec refs/*:refs/*
will end up asking to update refs/remotes/origin/HEAD with the
object at refs/remotes/origin/HEAD at the remote side, while asking
to update refs/remotes/origin/master the same way. Depending on the
order the two updates happen, the latter one would find that the
value of the ref before it is updated has changed from what the code
expects.
When the user asks to update the underlying ref via the symbolic ref
explicitly without using a wildcard refspec, e.g. "git fetch $there
refs/heads/master:refs/remotes/origin/HEAD", we should still let him
do so, but when expanding wildcard refs, it will result in a more
intuitive outcome if we simply ignore local symbolic refs.
As the purpose of the symbolic ref refs/remotes/origin/HEAD is to
follow the ref it points at (e.g. refs/remotes/origin/master), its
value would change when the underlying ref is updated.
Earlier commit da3efdb (receive-pack: detect aliased updates which
can occur with symrefs, 2010-04-19) fixed a similar issue for "git
push".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* This time with minimal tests and an updated log message.
remote.c | 13 ++++++++++++-
t/t5535-fetch-push-symref.sh | 42 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 1 deletion(-)
create mode 100755 t/t5535-fetch-push-symref.sh
diff --git a/remote.c b/remote.c
index 04fd9ea..a72748c 100644
--- a/remote.c
+++ b/remote.c
@@ -1370,6 +1370,16 @@ int branch_merge_matches(struct branch *branch,
return refname_match(branch->merge[i]->src, refname, ref_fetch_rules);
}
+static int ignore_symref_update(const char *refname)
+{
+ unsigned char sha1[20];
+ int flag;
+
+ if (!resolve_ref_unsafe(refname, sha1, 0, &flag))
+ return 0; /* non-existing refs are OK */
+ return (flag & REF_ISSYMREF);
+}
+
static struct ref *get_expanded_map(const struct ref *remote_refs,
const struct refspec *refspec)
{
@@ -1383,7 +1393,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
if (strchr(ref->name, '^'))
continue; /* a dereference item */
if (match_name_with_pattern(refspec->src, ref->name,
- refspec->dst, &expn_name)) {
+ refspec->dst, &expn_name) &&
+ !ignore_symref_update(expn_name)) {
struct ref *cpy = copy_ref(ref);
cpy->peer_ref = alloc_ref(expn_name);
diff --git a/t/t5535-fetch-push-symref.sh b/t/t5535-fetch-push-symref.sh
new file mode 100755
index 0000000..8ed58d2
--- /dev/null
+++ b/t/t5535-fetch-push-symref.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='avoiding conflicting update thru symref aliasing'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit one &&
+ git clone . src &&
+ git clone src dst1 &&
+ git clone src dst2 &&
+ test_commit two &&
+ ( cd src && git pull )
+'
+
+test_expect_success 'push' '
+ (
+ cd src &&
+ git push ../dst1 "refs/remotes/*:refs/remotes/*"
+ ) &&
+ git ls-remote src "refs/remotes/*" >expect &&
+ git ls-remote dst1 "refs/remotes/*" >actual &&
+ test_cmp expect actual &&
+ ( cd src && git symbolic-ref refs/remotes/origin/HEAD ) >expect &&
+ ( cd dst1 && git symbolic-ref refs/remotes/origin/HEAD ) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch' '
+ (
+ cd dst2 &&
+ git fetch ../src "refs/remotes/*:refs/remotes/*"
+ ) &&
+ git ls-remote src "refs/remotes/*" >expect &&
+ git ls-remote dst2 "refs/remotes/*" >actual &&
+ test_cmp expect actual &&
+ ( cd src && git symbolic-ref refs/remotes/origin/HEAD ) >expect &&
+ ( cd dst2 && git symbolic-ref refs/remotes/origin/HEAD ) >actual &&
+ test_cmp expect actual
+'
+
+test_done
--
1.8.1.rc1.128.gd8d1528
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox