* Applying changes across divergent branches
From: Tom Schutzer-Weissmann @ 2008-09-24 14:40 UTC (permalink / raw)
To: git
Hello all,
I am looking into how to apply git to some current working methods.
We tend to have two or three main branches: the development branch, and
one or two product branches. The development branch is the cutting edge,
and each product branches off from it.
While the product branch shares history with the development branch, not
all changes to the development branch will get applied to the product
branch. We tend to maintain two versions of a product at any time,
meaning two divergent product branches.
Could we use git, or a tool based on git, to change on the development
branch and selectively apply changes to the other branches - is it as
simple as using git cherry-pick?
Thanks in advance,
Tom SW
^ permalink raw reply
* Re: clone fails: Could not get the current working directory
From: Alex Riesen @ 2008-09-24 14:43 UTC (permalink / raw)
To: John Freeman; +Cc: git
In-Reply-To: <48DA410A.2080504@cs.tamu.edu>
2008/9/24 John Freeman <jfreeman@cs.tamu.edu>:
> Alex Riesen wrote:
>>
>> General question: What does Sun's pwd do?
>
> It works like you'd expect. There are no permission problems. Even in
> directories for which I don't have read access, it will show the path.
No, not what it shows. What does it call? Which syscalls it uses so we
can use them also. Or is /bin/pwd root-SUID?
^ permalink raw reply
* Re: [PATCH] add GIT_FAST_STAT mode for Cygwin
From: Alex Riesen @ 2008-09-24 14:42 UTC (permalink / raw)
To: Dmitry Potapov
Cc: git, Johannes Sixt, Junio C Hamano, Steffen Prohaska,
Shawn O. Pearce
In-Reply-To: <20080924140358.GX21650@dpotapov.dyndns.org>
2008/9/24 Dmitry Potapov <dpotapov@gmail.com>:
> it works fine in almost all practical cases I aware of, but I cannot
> guarantee identical behavior in _all_ cases.
Well, make it as good as MSys/Cygwin's and no one asks for your guarantee.
> Frankly, I don't have strong preference here neither for making this
> fast version always work nor leave it conditional (perhaps, with the
> default setting use-fast-version). So, whatever the majority decides
> is fine with me.
I'm voting for compile-time configuration then.
>> Besides it will remove your setup code, which looks bigger and provoked
>> more discussion than the real subject itself.
>
> I believe Shawn wanted it to be configurable on per-repository basis.
which, I believe, is pointless.
^ permalink raw reply
* Re: Partial tree export and merging
From: Shawn O. Pearce @ 2008-09-24 14:39 UTC (permalink / raw)
To: Heiko Voigt; +Cc: git, Jens Lehmann
In-Reply-To: <48DA476F.1070700@mahr.de>
Heiko Voigt <heiko.voigt@mahr.de> wrote:
>
> I am currently facing a challenge for adding limited access to a git
> repository for the i18n and documentation (language) team.
...
> To archieve this I would like to extract a repository that only contains
> the documentation and localization files which can be used by the i8n
> and doc team. This should be regularly merged into the development (with
> code) repository.
>
> My idea of a solution would be to export patches only for the specific
> files and import them into a seperate empty repository/branch using
> git-format-patch and git-am. This seperate repository then itself then
> could be imported again with a normal merge operation. Has a anyone
> already solved such a problem or other ideas how to solve this ?
See git-filter-branch. You can use it to slice the history down
to only contain these files, but still show the full change history
of them (assuming that is what you are trying to get).
Once the history is split into a new "doc+html" repository have
developers _only_ edit the docs/html in the doc+html repository,
don't make more edits in the source code repository.
You can use git-submodule or git-merge with the subtree strategy
to pull changes from the doc+html repository into the main source
repository.
--
Shawn.
^ permalink raw reply
* Partial tree export and merging
From: Heiko Voigt @ 2008-09-24 13:58 UTC (permalink / raw)
To: git; +Cc: Jens Lehmann
In-Reply-To: <48D9FACB.20901@mahr.de>
Hallo,
I am currently facing a challenge for adding limited access to a git
repository for the i18n and documentation (language) team. Our
repository contains *.html and *.loc files which are located along with
the code. The language team should not see the code. At the same time a
developer using the full tree needs to be able to contribute to the i8n
files.
To archieve this I would like to extract a repository that only contains
the documentation and localization files which can be used by the i8n
and doc team. This should be regularly merged into the development (with
code) repository.
My idea of a solution would be to export patches only for the specific
files and import them into a seperate empty repository/branch using
git-format-patch and git-am. This seperate repository then itself then
could be imported again with a normal merge operation. Has a anyone
already solved such a problem or other ideas how to solve this ?
cheers Heiko
^ permalink raw reply
* Re: [PATCH] gitk: Update swedish translation.
From: Peter Krefting @ 2008-09-24 14:31 UTC (permalink / raw)
To: Mikael Magnusson; +Cc: Paul Mackerras, Git Mailing List
In-Reply-To: <237967ef0809232333y40e36d6bs3205091e3baa701c@mail.gmail.com>
Mikael Magnusson:
Looks good! A few corrections:
> +#: gitk:327
> +msgid "Error executing --argscmd command:"
> +msgstr "Fel vid körning av --argscmd kommando:"
The word is incorrectly split (särskrivning).
"Fel vid körning av --argscmd-kommandot:"
would be better (note the change to determined form).
> +#: gitk:2218
> +msgid "Blame parent commit"
> +msgstr "Kör blame på föregående incheckning"
"Blame" should probably be translated. git-gui uses "annotate", which
is easier to understand, so possible:
"Annotera föregående incheckning"
> +#: gitk:2997 gitk:3006
> +#, tcl-format
> +msgid "Error creating temporary directory %s:"
> +msgstr "Fel vid skapande av tillfällig katalog %s:"
The "-ande" form makes reading strange.
"Fel när tillfällig katalog %s skapades:"
or something similar
> +#: gitk:3039
> +msgid "No such commit"
> +msgstr "Ingen sådan incheckning finns"
It looks like it is constrained for space, but you should check that.
If it is, something like "Incheckning saknas" would work.
> +#: gitk:3044
> +msgid "git gui blame: command failed:"
> +msgstr "git gui blame: kommando misslyckades"
Your missing a final colon, and it should be determined form:
"git gui blame: kommandot misslyckades:"
--
\\// Peter - http://www.softwolves.pp.se/
^ permalink raw reply
* Re: [PATCH] add GIT_FAST_STAT mode for Cygwin
From: Dmitry Potapov @ 2008-09-24 14:03 UTC (permalink / raw)
To: Alex Riesen
Cc: git, Johannes Sixt, Junio C Hamano, Steffen Prohaska,
Shawn O. Pearce
In-Reply-To: <81b0412b0809240425t63a2a28cw1cc0c0d95b3290f7@mail.gmail.com>
On Wed, Sep 24, 2008 at 01:25:06PM +0200, Alex Riesen wrote:
> 2008/9/23 Dmitry Potapov <dpotapov@gmail.com>:
> >
> > I thought that in rather unusual circumstances (such as using Cygwin
> > mount to connect separately directories in one tree), this fast version
> > may not work. So, I made it conditional. It is runtime conditional,
> > because most users do not build Git themselves but install a ready
> > Cygwin package.
>
> So? How about make the fast version _always_ work? We don't seem
> to fallback to copy+unlink everytime the POSIX rename fails.
I am not sure that I understand your analogue here. First, rename has
never meant to work as copy+unlink. Second, I don't fall back on some
other code when the implementation provided by Cygwin fails. I replace
the Cygwin implementation with a faster but a bit hackish version. Yes,
it works fine in almost all practical cases I aware of, but I cannot
guarantee identical behavior in _all_ cases.
Frankly, I don't have strong preference here neither for making this
fast version always work nor leave it conditional (perhaps, with the
default setting use-fast-version). So, whatever the majority decides
is fine with me.
> Besides it will remove your setup code, which looks bigger and provoked
> more discussion than the real subject itself.
I believe Shawn wanted it to be configurable on per-repository basis.
I have just finished re-writing the code in the way he suggested, so I
hope all objections with the setup code are resolved now. I will send
the new version a bit later, I did not have time to test it yet.
Dmitry
^ permalink raw reply
* Re: clone fails: Could not get the current working directory
From: John Freeman @ 2008-09-24 13:30 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <81b0412b0809240430y682d6dd9wef801c33a6ee2f85@mail.gmail.com>
Alex Riesen wrote:
> General question: What does Sun's pwd do?
>
It works like you'd expect. There are no permission problems. Even in
directories for which I don't have read access, it will show the path.
- John
^ permalink raw reply
* Re: clone fails: Could not get the current working directory
From: Alex Riesen @ 2008-09-24 11:30 UTC (permalink / raw)
To: John Freeman; +Cc: git
In-Reply-To: <48D95C96.4030906@cs.tamu.edu>
2008/9/23 John Freeman <jfreeman@cs.tamu.edu>:
> Alex Riesen wrote:
>> Again: try a simple program which just does getpwd for this pathname
>
> From what I gather, getpwd() is in libiberty, which I didn't feel like
> messing with for this example. I ran a small test program that called
> getcwd() in the repo directory, and it failed. errno was set to EACCES,
> indicating insufficient permissions.
So there we are...
> http://www.opengroup.org/onlinepubs/009695399/functions/getcwd.html
It suggest a rather dubious workaround (calling pwd).
> I may get around later to patching this, but for now we're moving ahead with
> a workaround.
...but that's a system-inflicted workaround. We just have to do it or something
like what it does.
General question: What does Sun's pwd do?
^ permalink raw reply
* Re: [PATCH] add GIT_FAST_STAT mode for Cygwin
From: Alex Riesen @ 2008-09-24 11:25 UTC (permalink / raw)
To: Dmitry Potapov; +Cc: git, Johannes Sixt, Junio C Hamano, Steffen Prohaska
In-Reply-To: <20080923165247.GO21650@dpotapov.dyndns.org>
2008/9/23 Dmitry Potapov <dpotapov@gmail.com>:
> On Tue, Sep 23, 2008 at 04:37:14PM +0200, Alex Riesen wrote:
>> 2008/9/23 Dmitry Potapov <dpotapov@gmail.com>:
>> >
>> > This fast mode works only for relative paths. It is assumed that the
>> > whole repository is located inside one directory without using Cygwin
>> > mount to bind external paths inside of the current tree.
>>
>> Why runtime conditional? Why conditional at all?
>
> I thought that in rather unusual circumstances (such as using Cygwin
> mount to connect separately directories in one tree), this fast version
> may not work. So, I made it conditional. It is runtime conditional,
> because most users do not build Git themselves but install a ready
> Cygwin package.
So? How about make the fast version _always_ work? We don't seem
to fallback to copy+unlink everytime the POSIX rename fails.
Besides it will remove your setup code, which looks bigger and provoked
more discussion than the real subject itself.
^ permalink raw reply
* Re: TopGit: how to deal with upstream inclusion
From: martin f krafft @ 2008-09-24 11:21 UTC (permalink / raw)
To: Petr Baudis, git
In-Reply-To: <20080923095528.GR10360@machine.or.cz>
[-- Attachment #1: Type: text/plain, Size: 849 bytes --]
also sprach Petr Baudis <pasky@suse.cz> [2008.09.23.1155 +0200]:
> > Well, but what if upstream implemented our solution slightly
> > differently, and if it's only because they used tabs instead of
> > spaces? We wouldn't want -s ours then, huh?
>
> You still would want to get tabs in other patches that depended on
> the merged one, no? Otherwise tg patch output will produce patches
> that do not apply and tg export will change the tabs back to
> spaces.
I would want to have to resolve all dependent branches and change
them to use tabs, right. But since I used spaces and they used tabs,
using -s ours would give preference to spaces, no?
--
martin | http://madduck.net/ | http://two.sentenc.es/
the reason the mainstream is thought of as a stream
is because it is so shallow.
spamtraps: madduck.bogus@madduck.net
[-- Attachment #2: Digital signature (see http://martin-krafft.net/gpg/) --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: Git submodule enhancements
From: P. Christeas @ 2008-09-24 10:14 UTC (permalink / raw)
To: Lars Hjemli; +Cc: Git Mailing List
In-Reply-To: <8c5c35580809240213v5198d2abh489915dc1133c75@mail.gmail.com>
On Wednesday 24 September 2008, Lars Hjemli wrote:
> It looks like --cloned requires the downstream to know which
> submodules are available from the same remote as the supermodule (and
> with the same path as registered in the supermodule), i.e. quite a
> specific configuration. Is this really common enough to justify a
> special option to `submodule init`?
I agree. My patch is only a temporary fix for the situation and may not cover
all needs.
> Maybe the .gitmodules file could be extended to contain multiple urls
> instead (i.e. both absolute and relative ones)? Then `submodule init`
> could get options like --prefer-relative-url, --prefer-absolute-url
> and --interactive. What do you think?
I guess there is much room for improvement wrt. with the .gitmodules . For
one, they should try to mimic the 'git clone' refspec logic, instead of being
a static file. (in fact, the hooks could let us do that using scripts alone)
> Hmm, after reading through this once more I guess you're trying to
> clone a non-bare repository, possibly also lacking a .gitmodules file
> (hence the --force)?
Not really. I was trying to have the git-submodule script re-write the conf
with a different url. Merely like running a 'submodule sync' at the same
time.
> Btw: why doesn't
> $ git submodule foreach 'git archive HEAD > somewhere/$path.tar'
> work for you?
In fact, it could. You could also replace HEAD with the $sha1 ..
In general, my comment on submodules is that it is a very powerful concept,
but still lacks many real-life features. Reading the C code, I realized that
we would have to rework all the core plumbing of git in order to have it work
accross different git repos inside the same C process. That is a stopper.
Otherwise, if we could only have read_tree_recursive() span to different gits,
we could do really beautiful things.
Sorry for posting many ideas and only few patches!
^ permalink raw reply
* [PATCH] Fixed some grammatical errors in git-rebase.txt documentation.
From: Garry Dolley @ 2008-09-24 9:51 UTC (permalink / raw)
To: git; +Cc: Garry Dolley
Generally, the dependent clause "for example" is suffixed with a comma.
Used present tense where appropriate to be consistent with the other
paragraphs.
Rewrote the paragraph in the second hunk to be more clear.
Signed-off-by: Garry Dolley <gdolley@ucla.edu>
---
Documentation/git-rebase.txt | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 59c1b02..32f0f12 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -92,7 +92,7 @@ branch to another, to pretend that you forked the topic branch
from the latter branch, using `rebase --onto`.
First let's assume your 'topic' is based on branch 'next'.
-For example feature developed in 'topic' depends on some
+For example, a feature developed in 'topic' depends on some
functionality which is found in 'next'.
------------
@@ -103,9 +103,9 @@ functionality which is found in 'next'.
o---o---o topic
------------
-We would want to make 'topic' forked from branch 'master',
-for example because the functionality 'topic' branch depend on
-got merged into more stable 'master' branch, like this:
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
------------
o---o---o---o---o master
--
1.6.0.1
^ permalink raw reply related
* Re: Git submodule enhancements
From: Lars Hjemli @ 2008-09-24 9:46 UTC (permalink / raw)
To: P. Christeas; +Cc: Git Mailing List
In-Reply-To: <8c5c35580809240213v5198d2abh489915dc1133c75@mail.gmail.com>
On Wed, Sep 24, 2008 at 11:13 AM, Lars Hjemli <hjemli@gmail.com> wrote:
> On Wed, Sep 24, 2008 at 10:00 AM, P. Christeas <p_christ@hol.gr> wrote:
> Subject: [PATCH] Git submodule archive: create series of archives, for
> each module
Btw: why doesn't
$ git submodule foreach 'git archive HEAD > somewhere/$path.tar'
work for you?
--
larsh
^ permalink raw reply
* [PATCH] Fix submodule sync with relative submodule URLs
From: Johan Herland @ 2008-09-24 9:31 UTC (permalink / raw)
To: git; +Cc: David Aguilar, Junio C Hamano, Mark Levedahl
In-Reply-To: <402731c90809240029l308726aeme14c0e7fe2d54a3c@mail.gmail.com>
Signed-off-by: Johan Herland <johan@herland.net>
---
On Wednesday 24 September 2008, David Aguilar wrote:
> Instead of just doing an "|| exit" shouldn't it report an explanation
> of the error?
> Other than that, it looks good to me.
Fixed. Thanks.
...Johan
git-submodule.sh | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index 1c39b59..f89bdbe 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -634,6 +634,15 @@ cmd_sync()
do
name=$(module_name "$path")
url=$(git config -f .gitmodules --get submodule."$name".url)
+
+ # Possibly a url relative to parent
+ case "$url" in
+ ./*|../*)
+ url=$(resolve_relative_url "$url") ||
+ die "failed to resolve relative submodule url for '$name'"
+ ;;
+ esac
+
if test -e "$path"/.git
then
(
--
1.6.0.2.463.g7f0eb
^ permalink raw reply related
* Re: [PATCH] maint: check return of split_cmdline to avoid bad config strings
From: Miklos Vajna @ 2008-09-24 9:28 UTC (permalink / raw)
To: Deskin Miller; +Cc: git, gitster
In-Reply-To: <20080924061028.GA2792@riemann.deskinm.fdns.net>
[-- Attachment #1: Type: text/plain, Size: 1541 bytes --]
On Wed, Sep 24, 2008 at 02:10:28AM -0400, Deskin Miller <deskinm@umich.edu> wrote:
> As the testcase demonstrates, it's possible to have split_cmdline return -1 and
> deallocate any memory it's allocated, if the config string is missing an end
> quote. In both the cases below, the return isn't checked, causing a pretty
> immediate segfault.
I think this could go to the commit message.
> diff --git a/builtin-merge.c b/builtin-merge.c
> index b280444..dcaf368 100644
> --- a/builtin-merge.c
> +++ b/builtin-merge.c
> @@ -442,6 +442,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
>
> buf = xstrdup(v);
> argc = split_cmdline(buf, &argv);
> + if (argc < 0)
> + die("Bad branch.%s.mergeoptions string", branch);
> argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
> memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
> argc++;
ACK.
> diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
> index 64567fb..3794d23 100755
> --- a/t/t1300-repo-config.sh
> +++ b/t/t1300-repo-config.sh
> @@ -741,4 +741,14 @@ test_expect_success 'symlinked configuration' '
>
> '
>
> +test_expect_success 'check split_cmdline return' "
> + git config alias.split-cmdline-fix 'echo \"' &&
> + git split-cmdline-fix || test \$? = 128 &&
> + echo foo > foo &&
> + git add foo &&
> + git commit -m 'initial commit' &&
> + git config branch.master.mergeoptions 'echo \"' &&
> + git merge master || test \$? = 128
> + "
Why don't you use test_must_fail here?
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: Git submodule enhancements
From: Lars Hjemli @ 2008-09-24 9:25 UTC (permalink / raw)
To: P. Christeas; +Cc: Git Mailing List
In-Reply-To: <8c5c35580809240213v5198d2abh489915dc1133c75@mail.gmail.com>
On Wed, Sep 24, 2008 at 11:13 AM, Lars Hjemli <hjemli@gmail.com> wrote:
> On Wed, Sep 24, 2008 at 10:00 AM, P. Christeas <p_christ@hol.gr> wrote:
> + # Cloned mode: we try to figure out the submodule
> + # path in the remote origin.
> + # FIXME: we do use "../" because the remote is the .git/
> + url=$(resolve_relative_url "../$path/.git")
> + fi
> +
> git config submodule."$name".url "$url" ||
> die "Failed to register url for submodule path '$path'"
> --
> 1.6.0.1
>
>
> It looks like --cloned requires the downstream to know which
> submodules are available from the same remote as the supermodule (and
> with the same path as registered in the supermodule)
Hmm, after reading through this once more I guess you're trying to
clone a non-bare repository, possibly also lacking a .gitmodules file
(hence the --force)?
--
larsh
^ permalink raw reply
* Re: Git submodule enhancements
From: Lars Hjemli @ 2008-09-24 9:13 UTC (permalink / raw)
To: P. Christeas; +Cc: Git Mailing List
In-Reply-To: <200809241100.30758.p_christ@hol.gr>
On Wed, Sep 24, 2008 at 10:00 AM, P. Christeas <p_christ@hol.gr> wrote:
> In my attempt to take some source off a submoduled repo, I tried writting a
> few lines of code into git-submodule.
Thanks, but please also send this to git@vger.kernel.org. And please
try do inline the patches, it makes it much easier to review; I've
pasted the patches below and inserted a few comments prefixed with
'lh>'.
>From 9edad86468933a21264ab7bed4608ea8a6e992e4 Mon Sep 17 00:00:00 2001
From: P. Christeas <p_christ@hol.gr>
Date: Wed, 24 Sep 2008 10:05:45 +0300
Subject: [PATCH] Git submodule archive: create series of archives, for
each module
This is a temporary solution to creating archives from repos
containing submodules. It will just create a series of archives,
each named after the name of the submodule.
---
git-submodule.sh | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index 1c39b59..2bce7f9 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -602,6 +602,91 @@ cmd_status()
fi
done
}
+
+cmd_archive() {
+ # parse $args after "submodule ... archive".
+ smodules=""
+ verbose=""
+ format=tar
+ do_exec=
+ base_prefix=""
+ outname=
+ while test $# -ne 0
+ do
+ case "$1" in
+ -q|--quiet)
+ quiet=1
+ ;;
+ -m|--module)
+ shift
+ smodules+="$1 "
+ ;;
lh> Other submodule commands take optional module paths as final
lh> arguments. Why not use the same for `archive`?
+ --format)
+ shift
+ format="$1"
+ ;;
+ --exec)
+ shift
+ do_exec="--exec=$1"
+ ;;
+ --prefix)
+ shift
+ base_prefix="$1"
+ ;;
+ -v|--verbose)
+ verbose="-v"
+ ;;
+ -o|--output)
+ shift
+ outname="$1"
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+ done
+ if [ -z $outname ] ; then
+ outname=$(basename $(pwd))-%m.$format
+ fi
+
+ if ! (echo $outname | grep '%m') > /dev/null ; then
+ outname+="-%m"
+ fi
+ if ! (echo $outname | grep '^/') > /dev/null ; then
+ outname=$(pwd)/"$outname"
+ fi
+
+ #echo "Modules: $smodules"
+ #echo "Params: $@"
+ #echo "Outname: $outname"
lh> Please remove debug comments.
+
+ module_list "$smodules" |
+ while read mode sha1 stage path
+ do
+ name=$(module_name "$path") || exit
+# url=$(git config submodule."$name".url)
+# if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
+# then
+# say "-$sha1 $path"
+# continue;
+# fi
lh> This should probably work similar to `update`, i.e. exit
lh> with an error if a submodule path is explicitly specified
lh> and the submodule isn't registered in .git/config, and
lh> silently skip any non-registered submodules if no
lh> paths were specified. And if the submodule is not
lh> skipped it probably should be an error if the submodule
lh> isn't checked out.
+
+ fname=$(echo $outname |sed 's/%m/'$name'/')
lh> This should probably be documented ;-)
+ say $fname
+ pushd "$path" > /dev/null
+ git archive --format=$format $do_exec $verbose
--prefix="$base_prefix$path/" $sha1 > \
+ "$fname"
+ popd > /dev/null
lh> What does `git archive` do when --exec is specified without
lh> --remote? What about error checking?
+ done
+}
#
# Sync remote urls for submodules
# This makes the value for remote.$remote.url match the value
@@ -656,7 +741,7 @@ cmd_sync()
while test $# != 0 && test -z "$command"
do
case "$1" in
- add | foreach | init | update | status | summary | sync)
+ add | foreach | init | update | status | summary | sync | archive)
command=$1
;;
-q|--quiet)
--
1.6.0.1
>From 87b75f003d31994d0de6502342e4d0ad68665e80 Mon Sep 17 00:00:00 2001
From: P. Christeas <p_christ@hol.gr>
Date: Wed, 24 Sep 2008 10:48:04 +0300
Subject: [PATCH] Submodule init: cloned mode
If we try to clone a repo with git submodules, the 'submodule init'
command should bind the submodules to the source repo, rather than
the source's origin.
Signed-off-by: P. Christeas <p_christ@hol.gr>
---
git-submodule.sh | 37 +++++++++++++++++++++++++------------
1 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index 2bce7f9..df5fcac 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -241,6 +241,12 @@ cmd_init()
-q|--quiet)
quiet=1
;;
+ -f|--force)
+ force=1
+ ;;
+ --cloned)
+ cloned=1
+ ;;
--)
shift
break
@@ -261,19 +267,26 @@ cmd_init()
# Skip already registered paths
name=$(module_name "$path") || exit
url=$(git config submodule."$name".url)
- test -z "$url" || continue
-
- url=$(git config -f .gitmodules submodule."$name".url)
- test -z "$url" &&
- die "No url found for submodule path '$path' in .gitmodules"
-
- # Possibly a url relative to parent
- case "$url" in
- ./*|../*)
- url=$(resolve_relative_url "$url") || exit
- ;;
- esac
+ test -z "$url" || test -n "$force" || continue
+ if [ "x$cloned" != "x1" ] ; then
+ url=$(git config -f .gitmodules submodule."$name".url)
+ test -z "$url" &&
+ die "No url found for submodule path '$path' in .gitmodules"
+
+ # Possibly a url relative to parent
+ case "$url" in
+ ./*|../*)
+ url=$(resolve_relative_url "$url") || exit
+ ;;
+ esac
+ else
+ # Cloned mode: we try to figure out the submodule
+ # path in the remote origin.
+ # FIXME: we do use "../" because the remote is the .git/
+ url=$(resolve_relative_url "../$path/.git")
+ fi
+
git config submodule."$name".url "$url" ||
die "Failed to register url for submodule path '$path'"
--
1.6.0.1
It looks like --cloned requires the downstream to know which
submodules are available from the same remote as the supermodule (and
with the same path as registered in the supermodule), i.e. quite a
specific configuration. Is this really common enough to justify a
special option to `submodule init`?
Maybe the .gitmodules file could be extended to contain multiple urls
instead (i.e. both absolute and relative ones)? Then `submodule init`
could get options like --prefer-relative-url, --prefer-absolute-url
and --interactive. What do you think?
--
larsh
^ permalink raw reply related
* Re: [PATCH] Fix submodule sync with relative submodule URLs
From: David Aguilar @ 2008-09-24 7:29 UTC (permalink / raw)
To: Johan Herland; +Cc: Junio C Hamano, git, Mark Levedahl
In-Reply-To: <200809221808.31730.johan@herland.net>
On Mon, Sep 22, 2008 at 9:08 AM, Johan Herland <johan@herland.net> wrote:
> Signed-off-by: Johan Herland <johan@herland.net>
> ---
> git-submodule.sh | 8 ++++++++
> 1 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 1c39b59..92be0fe 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -634,6 +634,14 @@ cmd_sync()
> do
> name=$(module_name "$path")
> url=$(git config -f .gitmodules --get submodule."$name".url)
> +
> + # Possibly a url relative to parent
> + case "$url" in
> + ./*|../*)
> + url=$(resolve_relative_url "$url") || exit
> + ;;
> + esac
> +
> if test -e "$path"/.git
> then
> (
> --
> 1.6.0.1.400.gd2470
>
Instead of just doing an "|| exit" shouldn't it report an explanation
of the error?
Other than that, it looks good to me.
Mark, Junio?
--
David
^ permalink raw reply
* Re: [PATCH 1/3] Prepare for non-interactive merge-preserving rebase
From: Andreas Ericsson @ 2008-09-24 7:13 UTC (permalink / raw)
To: SZEDER Gábor; +Cc: Stephen Haberman, Git Mailing List, Junio C Hamano
In-Reply-To: <20080924001027.GA19264@neumann>
SZEDER Gábor wrote:
> Hi Andreas,
>
> First of all, thanks for the work!
>
> On Tue, Sep 23, 2008 at 11:30:09PM +0200, Andreas Ericsson wrote:
>> It requires a bit of testing though. All the t/t34* tests pass with
>> all the patches applied, and some manual tries worked just fine too,
>> but if you wanna give it a twirl where you work, that'd be great.
> Unfortunately in my example workflow[1] posted earlier today your
> patch series does not work in the way I would like it to behave.
>
> The following DAG is created by the commands below:
>
> -A---B master
> \
> C---M topic
> \ /
> D
>
> git init
> echo 1 >foo
> git add foo
> git commit -m 'first on master' # A
> echo 2 >>foo
> git commit -m 'second on master' foo # B
> git checkout -b topic HEAD^
> echo 1 >bar
> git add bar
> git commit -m 'first on topic' # C
> git checkout -b subtopic
> echo 1 >baz
> git add baz
> git commit -m 'first on subtopic' # D
> git checkout topic
> git merge --no-ff subtopic # M
>
> If I now execute 'git rebase -p master topic', I get the following:
>
> -A---B master
> \ \
> \ C'---M' topic
> \ /
> C----D
>
> But I would rather like to have the following:
>
> -A---B master
> \
> C'---M' topic
> \ /
> D'
>
> Would such a behaviour possible at all?
>
See Johannes Sixt's reply (git sequencer).
What I provided was a hack to access existing functionality in a way
that was previously not possible. While that can be neat in itself,
the patch series doesn't alter how the merge-preserving rebase works
in the slightest.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* [PATCH] gitk: Update swedish translation.
From: Mikael Magnusson @ 2008-09-24 6:33 UTC (permalink / raw)
To: Paul Mackerras, Git Mailing List
[-- Attachment #1: Type: text/plain, Size: 31 bytes --]
attached
--
Mikael Magnusson
[-- Attachment #2: 0001-Update-swedish-translation.patch --]
[-- Type: application/octet-stream, Size: 24326 bytes --]
From 9d9791201f93f9096cb6e1b2798d71bb84a14100 Mon Sep 17 00:00:00 2001
From: Mikael Magnusson <mikachu@gmail.com>
Date: Wed, 24 Sep 2008 08:29:21 +0200
Subject: [PATCH] gitk: Update swedish translation.
Signed-Off-By: Mikael Magnusson <mikachu@gmail.com>
---
po/sv.po | 460 +++++++++++++++++++++++++++++++++----------------------------
1 files changed, 249 insertions(+), 211 deletions(-)
diff --git a/po/sv.po b/po/sv.po
index e1ecfb7..f67f68f 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sv\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-03 18:58+0200\n"
+"POT-Creation-Date: 2008-09-24 08:23+0200\n"
"PO-Revision-Date: 2008-08-03 19:03+0200\n"
"Last-Translator: Mikael Magnusson <mikachu@gmail.com>\n"
"Language-Team: Swedish <sv@li.org>\n"
@@ -16,17 +16,25 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: gitk:102
+#: gitk:113
msgid "Couldn't get list of unmerged files:"
msgstr "Kunde inta hämta lista över ej sammanslagna filer:"
-#: gitk:329
+#: gitk:272
+msgid "Error parsing revisions:"
+msgstr "Fel vid tolkning av revisioner:"
+
+#: gitk:327
+msgid "Error executing --argscmd command:"
+msgstr "Fel vid körning av --argscmd kommando:"
+
+#: gitk:340
msgid "No files selected: --merge specified but no files are unmerged."
msgstr ""
"Inga filer valdes: --merge angavs men det finns inga filer som inte har "
"slagits samman."
-#: gitk:332
+#: gitk:343
msgid ""
"No files selected: --merge specified but no unmerged files are within file "
"limit."
@@ -34,257 +42,261 @@ msgstr ""
"Inga filer valdes: --merge angavs men det finns inga filer inom "
"filbegränsningen."
-#: gitk:354
+#: gitk:365 gitk:503
msgid "Error executing git log:"
msgstr "Fel vid körning av git log:"
-#: gitk:369
+#: gitk:378
msgid "Reading"
msgstr "Läser"
-#: gitk:400 gitk:3356
+#: gitk:438 gitk:3433
msgid "Reading commits..."
msgstr "Läser incheckningar..."
-#: gitk:403 gitk:1480 gitk:3359
+#: gitk:441 gitk:1528 gitk:3436
msgid "No commits selected"
msgstr "Inga incheckningar markerade"
-#: gitk:1358
+#: gitk:1399
msgid "Can't parse git log output:"
msgstr "Kan inte tolka utdata från git log:"
-#: gitk:1557
+#: gitk:1605
msgid "No commit information available"
msgstr "Ingen incheckningsinformation är tillgänglig"
-#: gitk:1654 gitk:1676 gitk:3150 gitk:7620 gitk:9149 gitk:9317
+#: gitk:1709 gitk:1731 gitk:3230 gitk:7701 gitk:9230 gitk:9398
msgid "OK"
msgstr "OK"
-#: gitk:1678 gitk:3151 gitk:7296 gitk:7367 gitk:7470 gitk:7516 gitk:7622
-#: gitk:9150 gitk:9318
+#: gitk:1733 gitk:3231 gitk:7377 gitk:7448 gitk:7551 gitk:7597 gitk:7703
+#: gitk:9231 gitk:9399
msgid "Cancel"
msgstr "Avbryt"
-#: gitk:1716
+#: gitk:1771
msgid "File"
msgstr "Arkiv"
-#: gitk:1718
+#: gitk:1773
msgid "Update"
msgstr "Uppdatera"
-#: gitk:1719
+#: gitk:1774
msgid "Reload"
msgstr "Ladda om"
-#: gitk:1720
+#: gitk:1775
msgid "Reread references"
msgstr "Läs om referenser"
-#: gitk:1721
+#: gitk:1776
msgid "List references"
msgstr "Visa referenser"
-#: gitk:1722
+#: gitk:1777
msgid "Quit"
msgstr "Avsluta"
-#: gitk:1724
+#: gitk:1779
msgid "Edit"
msgstr "Redigera"
-#: gitk:1725
+#: gitk:1780
msgid "Preferences"
msgstr "Inställningar"
-#: gitk:1728 gitk:3087
+#: gitk:1783 gitk:3167
msgid "View"
msgstr "Visa"
-#: gitk:1729
+#: gitk:1784
msgid "New view..."
msgstr "Ny vy..."
-#: gitk:1730 gitk:3298 gitk:9932
+#: gitk:1785 gitk:3378 gitk:10030
msgid "Edit view..."
msgstr "Ändra vy..."
-#: gitk:1732 gitk:3299 gitk:9933
+#: gitk:1787 gitk:3379 gitk:10031
msgid "Delete view"
msgstr "Ta bort vy"
-#: gitk:1734
+#: gitk:1789
msgid "All files"
msgstr "Alla filer"
-#: gitk:1738
+#: gitk:1793
msgid "Help"
msgstr "Hjälp"
-#: gitk:1739 gitk:2399
+#: gitk:1794 gitk:2458
msgid "About gitk"
msgstr "Om gitk"
-#: gitk:1740
+#: gitk:1795
msgid "Key bindings"
msgstr "Tangentbordsbindningar"
-#: gitk:1797
+#: gitk:1852
msgid "SHA1 ID: "
msgstr "SHA1-id: "
-#: gitk:1828
+#: gitk:1883
msgid "Row"
msgstr "Rad"
-#: gitk:1859
+#: gitk:1914
msgid "Find"
msgstr "Sök"
-#: gitk:1860
+#: gitk:1915
msgid "next"
msgstr "nästa"
-#: gitk:1861
+#: gitk:1916
msgid "prev"
msgstr "föreg"
-#: gitk:1862
+#: gitk:1917
msgid "commit"
msgstr "incheckning"
-#: gitk:1865 gitk:1867 gitk:3511 gitk:3534 gitk:3558 gitk:5441 gitk:5512
+#: gitk:1920 gitk:1922 gitk:3588 gitk:3611 gitk:3635 gitk:5521 gitk:5592
msgid "containing:"
msgstr "som innehåller:"
-#: gitk:1868 gitk:2866 gitk:2871 gitk:3586
+#: gitk:1923 gitk:2925 gitk:2930 gitk:3663
msgid "touching paths:"
msgstr "som rör sökväg:"
-#: gitk:1869 gitk:3591
+#: gitk:1924 gitk:3668
msgid "adding/removing string:"
msgstr "som lägger/till tar bort sträng:"
-#: gitk:1878 gitk:1880
+#: gitk:1933 gitk:1935
msgid "Exact"
msgstr "Exakt"
-#: gitk:1880 gitk:3667 gitk:5409
+#: gitk:1935 gitk:3744 gitk:5489
msgid "IgnCase"
msgstr "IgnVersaler"
-#: gitk:1880 gitk:3560 gitk:3665 gitk:5405
+#: gitk:1935 gitk:3637 gitk:3742 gitk:5485
msgid "Regexp"
msgstr "Reg.uttr."
-#: gitk:1882 gitk:1883 gitk:3686 gitk:3716 gitk:3723 gitk:5532 gitk:5599
+#: gitk:1937 gitk:1938 gitk:3763 gitk:3793 gitk:3800 gitk:5612 gitk:5679
msgid "All fields"
msgstr "Alla fält"
-#: gitk:1883 gitk:3684 gitk:3716 gitk:5471
+#: gitk:1938 gitk:3761 gitk:3793 gitk:5551
msgid "Headline"
msgstr "Rubrik"
-#: gitk:1884 gitk:3684 gitk:5471 gitk:5599 gitk:6000
+#: gitk:1939 gitk:3761 gitk:5551 gitk:5679 gitk:6080
msgid "Comments"
msgstr "Kommentarer"
-#: gitk:1884 gitk:3684 gitk:3688 gitk:3723 gitk:5471 gitk:5936 gitk:7142
-#: gitk:7157
+#: gitk:1939 gitk:3761 gitk:3765 gitk:3800 gitk:5551 gitk:6016 gitk:7223
+#: gitk:7238
msgid "Author"
msgstr "Författare"
-#: gitk:1884 gitk:3684 gitk:5471 gitk:5938
+#: gitk:1939 gitk:3761 gitk:5551 gitk:6018
msgid "Committer"
msgstr "Incheckare"
-#: gitk:1913
+#: gitk:1968
msgid "Search"
msgstr "Sök"
-#: gitk:1920
+#: gitk:1975
msgid "Diff"
msgstr "Diff"
-#: gitk:1922
+#: gitk:1977
msgid "Old version"
msgstr "Gammal version"
-#: gitk:1924
+#: gitk:1979
msgid "New version"
msgstr "Ny version"
-#: gitk:1926
+#: gitk:1981
msgid "Lines of context"
msgstr "Rader sammanhang"
-#: gitk:1936
+#: gitk:1991
msgid "Ignore space change"
msgstr "Ignorera ändringar i blanksteg"
-#: gitk:1994
+#: gitk:2049
msgid "Patch"
msgstr "Patch"
-#: gitk:1996
+#: gitk:2051
msgid "Tree"
msgstr "Träd"
-#: gitk:2121 gitk:2136 gitk:7211
+#: gitk:2178 gitk:2193 gitk:7292
msgid "Diff this -> selected"
msgstr "Diff denna -> markerad"
-#: gitk:2123 gitk:2138 gitk:7212
+#: gitk:2180 gitk:2195 gitk:7293
msgid "Diff selected -> this"
msgstr "Diff markerad -> denna"
-#: gitk:2125 gitk:2140 gitk:7213
+#: gitk:2182 gitk:2197 gitk:7294
msgid "Make patch"
msgstr "Skapa patch"
-#: gitk:2126 gitk:7351
+#: gitk:2183 gitk:7432
msgid "Create tag"
msgstr "Skapa tagg"
-#: gitk:2127 gitk:7450
+#: gitk:2184 gitk:7531
msgid "Write commit to file"
msgstr "Skriv incheckning till fil"
-#: gitk:2128 gitk:7504
+#: gitk:2185 gitk:7585
msgid "Create new branch"
msgstr "Skapa ny gren"
-#: gitk:2129
+#: gitk:2186
msgid "Cherry-pick this commit"
msgstr "Plocka denna incheckning"
-#: gitk:2131
+#: gitk:2188
msgid "Reset HEAD branch to here"
msgstr "Återställ HEAD-grenen hit"
-#: gitk:2147
+#: gitk:2204
msgid "Check out this branch"
msgstr "Checka ut denna gren"
-#: gitk:2149
+#: gitk:2206
msgid "Remove this branch"
msgstr "Ta bort denna gren"
-#: gitk:2155
+#: gitk:2212
msgid "Highlight this too"
msgstr "Markera även detta"
-#: gitk:2157
+#: gitk:2214
msgid "Highlight this only"
msgstr "Markera bara detta"
-#: gitk:2159
+#: gitk:2216
msgid "External diff"
msgstr "Extern diff"
-#: gitk:2400
+#: gitk:2218
+msgid "Blame parent commit"
+msgstr "Kör blame på föregående incheckning"
+
+#: gitk:2459
msgid ""
"\n"
"Gitk - a commit viewer for git\n"
@@ -300,427 +312,453 @@ msgstr ""
"\n"
"Använd och vidareförmedla enligt villkoren i GNU General Public License"
-#: gitk:2408 gitk:2469 gitk:7799
+#: gitk:2467 gitk:2528 gitk:7880
msgid "Close"
msgstr "Stäng"
-#: gitk:2427
+#: gitk:2486
msgid "Gitk key bindings"
msgstr "Tangentbordsbindningar för Gitk"
-#: gitk:2429
+#: gitk:2488
msgid "Gitk key bindings:"
msgstr "Tangentbordsbindningar för Gitk:"
-#: gitk:2431
+#: gitk:2490
#, tcl-format
msgid "<%s-Q>\t\tQuit"
msgstr "<%s-Q>\t\tAvsluta"
-#: gitk:2432
+#: gitk:2491
msgid "<Home>\t\tMove to first commit"
msgstr "<Home>\t\tGå till första incheckning"
-#: gitk:2433
+#: gitk:2492
msgid "<End>\t\tMove to last commit"
msgstr "<End>\t\tGå till sista incheckning"
-#: gitk:2434
+#: gitk:2493
msgid "<Up>, p, i\tMove up one commit"
msgstr "<Upp>, p, i\tGå en incheckning upp"
-#: gitk:2435
+#: gitk:2494
msgid "<Down>, n, k\tMove down one commit"
msgstr "<Ned>, n, k\tGå en incheckning ned"
-#: gitk:2436
+#: gitk:2495
msgid "<Left>, z, j\tGo back in history list"
msgstr "<Vänster>, z, j\tGå bakåt i historiken"
-#: gitk:2437
+#: gitk:2496
msgid "<Right>, x, l\tGo forward in history list"
msgstr "<Höger>, x, l\tGå framåt i historiken"
-#: gitk:2438
+#: gitk:2497
msgid "<PageUp>\tMove up one page in commit list"
msgstr "<PageUp>\tGå upp en sida i incheckningslistan"
-#: gitk:2439
+#: gitk:2498
msgid "<PageDown>\tMove down one page in commit list"
msgstr "<PageDown>\tGå ned en sida i incheckningslistan"
-#: gitk:2440
+#: gitk:2499
#, tcl-format
msgid "<%s-Home>\tScroll to top of commit list"
msgstr "<%s-Home>\tRulla till början av incheckningslistan"
-#: gitk:2441
+#: gitk:2500
#, tcl-format
msgid "<%s-End>\tScroll to bottom of commit list"
msgstr "<%s-End>\tRulla till slutet av incheckningslistan"
-#: gitk:2442
+#: gitk:2501
#, tcl-format
msgid "<%s-Up>\tScroll commit list up one line"
msgstr "<%s-Upp>\tRulla incheckningslistan upp ett steg"
-#: gitk:2443
+#: gitk:2502
#, tcl-format
msgid "<%s-Down>\tScroll commit list down one line"
msgstr "<%s-Ned>\tRulla incheckningslistan ned ett steg"
-#: gitk:2444
+#: gitk:2503
#, tcl-format
msgid "<%s-PageUp>\tScroll commit list up one page"
msgstr "<%s-PageUp>\tRulla incheckningslistan upp en sida"
-#: gitk:2445
+#: gitk:2504
#, tcl-format
msgid "<%s-PageDown>\tScroll commit list down one page"
msgstr "<%s-PageDown>\tRulla incheckningslistan ned en sida"
-#: gitk:2446
+#: gitk:2505
msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
msgstr "<Skift-Upp>\tSök bakåt (uppåt, senare incheckningar)"
-#: gitk:2447
+#: gitk:2506
msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
msgstr "<Skift-Ned>\tSök framåt (nedåt, tidigare incheckningar)"
-#: gitk:2448
+#: gitk:2507
msgid "<Delete>, b\tScroll diff view up one page"
msgstr "<Delete>, b\tRulla diffvisningen upp en sida"
-#: gitk:2449
+#: gitk:2508
msgid "<Backspace>\tScroll diff view up one page"
msgstr "<Baksteg>\tRulla diffvisningen upp en sida"
-#: gitk:2450
+#: gitk:2509
msgid "<Space>\t\tScroll diff view down one page"
msgstr "<Blanksteg>\tRulla diffvisningen ned en sida"
-#: gitk:2451
+#: gitk:2510
msgid "u\t\tScroll diff view up 18 lines"
msgstr "u\t\tRulla diffvisningen upp 18 rader"
-#: gitk:2452
+#: gitk:2511
msgid "d\t\tScroll diff view down 18 lines"
msgstr "d\t\tRulla diffvisningen ned 18 rader"
-#: gitk:2453
+#: gitk:2512
#, tcl-format
msgid "<%s-F>\t\tFind"
msgstr "<%s-F>\t\tSök"
-#: gitk:2454
+#: gitk:2513
#, tcl-format
msgid "<%s-G>\t\tMove to next find hit"
msgstr "<%s-G>\t\tGå till nästa sökträff"
-#: gitk:2455
+#: gitk:2514
msgid "<Return>\tMove to next find hit"
msgstr "<Return>\t\tGå till nästa sökträff"
-#: gitk:2456
+#: gitk:2515
msgid "/\t\tMove to next find hit, or redo find"
msgstr "/\t\tGå till nästa sökträff, eller sök på nytt"
-#: gitk:2457
+#: gitk:2516
msgid "?\t\tMove to previous find hit"
msgstr "?\t\tGå till föregående sökträff"
-#: gitk:2458
+#: gitk:2517
msgid "f\t\tScroll diff view to next file"
msgstr "f\t\tRulla diffvisningen till nästa fil"
-#: gitk:2459
+#: gitk:2518
#, tcl-format
msgid "<%s-S>\t\tSearch for next hit in diff view"
msgstr "<%s-S>\t\tGå till nästa sökträff i diffvisningen"
-#: gitk:2460
+#: gitk:2519
#, tcl-format
msgid "<%s-R>\t\tSearch for previous hit in diff view"
msgstr "<%s-R>\t\tGå till föregående sökträff i diffvisningen"
-#: gitk:2461
+#: gitk:2520
#, tcl-format
msgid "<%s-KP+>\tIncrease font size"
msgstr "<%s-Num+>\tÖka teckenstorlek"
-#: gitk:2462
+#: gitk:2521
#, tcl-format
msgid "<%s-plus>\tIncrease font size"
msgstr "<%s-plus>\tÖka teckenstorlek"
-#: gitk:2463
+#: gitk:2522
#, tcl-format
msgid "<%s-KP->\tDecrease font size"
msgstr "<%s-Num->\tMinska teckenstorlek"
-#: gitk:2464
+#: gitk:2523
#, tcl-format
msgid "<%s-minus>\tDecrease font size"
msgstr "<%s-minus>\tMinska teckenstorlek"
-#: gitk:2465
+#: gitk:2524
msgid "<F5>\t\tUpdate"
msgstr "<F5>\t\tUppdatera"
-#: gitk:3091
+#: gitk:2940
+#, tcl-format
+msgid "Error getting \"%s\" from %s:"
+msgstr "Fel vid hämtning av \"%s\" från %s:"
+
+#: gitk:2997 gitk:3006
+#, tcl-format
+msgid "Error creating temporary directory %s:"
+msgstr "Fel vid skapande av tillfällig katalog %s:"
+
+#: gitk:3019
+msgid "command failed:"
+msgstr "kommando misslyckades:"
+
+#: gitk:3039
+msgid "No such commit"
+msgstr "Ingen sådan incheckning finns"
+
+#: gitk:3044
+msgid "git gui blame: command failed:"
+msgstr "git gui blame: kommando misslyckades"
+
+#: gitk:3053
+msgid "External diff viewer failed:"
+msgstr "Externt diff-verktyg misslyckades:"
+
+#: gitk:3171
msgid "Gitk view definition"
msgstr "Definition av Gitk-vy"
-#: gitk:3116
+#: gitk:3196
msgid "Name"
msgstr "Namn"
-#: gitk:3119
+#: gitk:3199
msgid "Remember this view"
msgstr "Spara denna vy"
-#: gitk:3123
+#: gitk:3203
msgid "Commits to include (arguments to git log):"
msgstr "Incheckningar att ta med (argument till git log):"
-#: gitk:3130
+#: gitk:3210
msgid "Command to generate more commits to include:"
msgstr "Kommando för att generera fler incheckningar att ta med:"
-#: gitk:3137
+#: gitk:3217
msgid "Enter files and directories to include, one per line:"
msgstr "Ange filer och kataloger att ta med, en per rad:"
-#: gitk:3184
+#: gitk:3264
msgid "Error in commit selection arguments:"
msgstr "Fel i argument för val av incheckningar:"
-#: gitk:3238 gitk:3290 gitk:3736 gitk:3750 gitk:4951 gitk:9896 gitk:9897
+#: gitk:3318 gitk:3370 gitk:3813 gitk:3827 gitk:5031 gitk:9994 gitk:9995
msgid "None"
msgstr "Inget"
-#: gitk:3684 gitk:5471 gitk:7144 gitk:7159
+#: gitk:3761 gitk:5551 gitk:7225 gitk:7240
msgid "Date"
msgstr "Datum"
-#: gitk:3684 gitk:5471
+#: gitk:3761 gitk:5551
msgid "CDate"
msgstr "Skapat datum"
-#: gitk:3833 gitk:3838
+#: gitk:3910 gitk:3915
msgid "Descendant"
msgstr "Avkomling"
-#: gitk:3834
+#: gitk:3911
msgid "Not descendant"
msgstr "Inte avkomling"
-#: gitk:3841 gitk:3846
+#: gitk:3918 gitk:3923
msgid "Ancestor"
msgstr "Förfader"
-#: gitk:3842
+#: gitk:3919
msgid "Not ancestor"
msgstr "Inte förfader"
-#: gitk:4078
+#: gitk:4158
msgid "Local changes checked in to index but not committed"
msgstr "Lokala ändringar sparade i indexet men inte incheckade"
-#: gitk:4111
+#: gitk:4191
msgid "Local uncommitted changes, not checked in to index"
msgstr "Lokala ändringar, ej sparade i indexet"
-#: gitk:5440
+#: gitk:5520
msgid "Searching"
msgstr "Söker"
-#: gitk:5940
+#: gitk:6020
msgid "Tags:"
msgstr "Taggar:"
-#: gitk:5957 gitk:5963 gitk:7137
+#: gitk:6037 gitk:6043 gitk:7218
msgid "Parent"
msgstr "Förälder"
-#: gitk:5968
+#: gitk:6048
msgid "Child"
msgstr "Barn"
-#: gitk:5977
+#: gitk:6057
msgid "Branch"
msgstr "Gren"
-#: gitk:5980
+#: gitk:6060
msgid "Follows"
msgstr "Följer"
-#: gitk:5983
+#: gitk:6063
msgid "Precedes"
msgstr "Föregår"
-#: gitk:6267
+#: gitk:6347
msgid "Error getting merge diffs:"
msgstr "Fel vid hämtning av sammanslagningsdiff:"
-#: gitk:6970
+#: gitk:7051
msgid "Goto:"
msgstr "Gå till:"
-#: gitk:6972
+#: gitk:7053
msgid "SHA1 ID:"
msgstr "SHA1-id:"
-#: gitk:6991
+#: gitk:7072
#, tcl-format
msgid "Short SHA1 id %s is ambiguous"
msgstr "Förkortat SHA1-id %s är tvetydigt"
-#: gitk:7003
+#: gitk:7084
#, tcl-format
msgid "SHA1 id %s is not known"
msgstr "SHA-id:t %s är inte känt"
-#: gitk:7005
+#: gitk:7086
#, tcl-format
msgid "Tag/Head %s is not known"
msgstr "Tagg/huvud %s är okänt"
-#: gitk:7147
+#: gitk:7228
msgid "Children"
msgstr "Barn"
-#: gitk:7204
+#: gitk:7285
#, tcl-format
msgid "Reset %s branch to here"
msgstr "Återställ grenen %s hit"
-#: gitk:7206
+#: gitk:7287
msgid "Detached head: can't reset"
msgstr "Frånkopplad head: kan inte återställa"
-#: gitk:7238
+#: gitk:7319
msgid "Top"
msgstr "Topp"
-#: gitk:7239
+#: gitk:7320
msgid "From"
msgstr "Från"
-#: gitk:7244
+#: gitk:7325
msgid "To"
msgstr "Till"
-#: gitk:7267
+#: gitk:7348
msgid "Generate patch"
msgstr "Generera patch"
-#: gitk:7269
+#: gitk:7350
msgid "From:"
msgstr "Från:"
-#: gitk:7278
+#: gitk:7359
msgid "To:"
msgstr "Till:"
-#: gitk:7287
+#: gitk:7368
msgid "Reverse"
msgstr "Vänd"
-#: gitk:7289 gitk:7464
+#: gitk:7370 gitk:7545
msgid "Output file:"
msgstr "Utdatafil:"
-#: gitk:7295
+#: gitk:7376
msgid "Generate"
msgstr "Generera"
-#: gitk:7331
+#: gitk:7412
msgid "Error creating patch:"
msgstr "Fel vid generering av patch:"
-#: gitk:7353 gitk:7452 gitk:7506
+#: gitk:7434 gitk:7533 gitk:7587
msgid "ID:"
msgstr "Id:"
-#: gitk:7362
+#: gitk:7443
msgid "Tag name:"
msgstr "Taggnamn:"
-#: gitk:7366 gitk:7515
+#: gitk:7447 gitk:7596
msgid "Create"
msgstr "Skapa"
-#: gitk:7381
+#: gitk:7462
msgid "No tag name specified"
msgstr "Inget taggnamn angavs"
-#: gitk:7385
+#: gitk:7466
#, tcl-format
msgid "Tag \"%s\" already exists"
msgstr "Taggen \"%s\" finns redan"
-#: gitk:7391
+#: gitk:7472
msgid "Error creating tag:"
msgstr "Fel vid skapande av tagg:"
-#: gitk:7461
+#: gitk:7542
msgid "Command:"
msgstr "Kommando:"
-#: gitk:7469
+#: gitk:7550
msgid "Write"
msgstr "Skriv"
-#: gitk:7485
+#: gitk:7566
msgid "Error writing commit:"
msgstr "Fel vid skrivning av incheckning:"
-#: gitk:7511
+#: gitk:7592
msgid "Name:"
msgstr "Namn:"
-#: gitk:7530
+#: gitk:7611
msgid "Please specify a name for the new branch"
msgstr "Ange ett namn för den nya grenen"
-#: gitk:7559
+#: gitk:7640
#, tcl-format
msgid "Commit %s is already included in branch %s -- really re-apply it?"
msgstr ""
"Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras "
"på nytt?"
-#: gitk:7564
+#: gitk:7645
msgid "Cherry-picking"
msgstr "Plockar"
-#: gitk:7576
+#: gitk:7657
msgid "No changes committed"
msgstr "Inga ändringar incheckade"
-#: gitk:7601
+#: gitk:7682
msgid "Confirm reset"
msgstr "Bekräfta återställning"
-#: gitk:7603
+#: gitk:7684
#, tcl-format
msgid "Reset branch %s to %s?"
msgstr "Återställa grenen %s till %s?"
-#: gitk:7607
+#: gitk:7688
msgid "Reset type:"
msgstr "Typ av återställning:"
-#: gitk:7611
+#: gitk:7692
msgid "Soft: Leave working tree and index untouched"
msgstr "Mjuk: Rör inte utcheckning och index"
-#: gitk:7614
+#: gitk:7695
msgid "Mixed: Leave working tree untouched, reset index"
msgstr "Blandad: Rör inte utcheckning, återställ index"
-#: gitk:7617
+#: gitk:7698
msgid ""
"Hard: Reset working tree and index\n"
"(discard ALL local changes)"
@@ -728,19 +766,19 @@ msgstr ""
"Hård: Återställ utcheckning och index\n"
"(förkastar ALLA lokala ändringar)"
-#: gitk:7633
+#: gitk:7714
msgid "Resetting"
msgstr "Återställer"
-#: gitk:7690
+#: gitk:7771
msgid "Checking out"
msgstr "Checkar ut"
-#: gitk:7741
+#: gitk:7822
msgid "Cannot delete the currently checked-out branch"
msgstr "Kan inte ta bort den just nu utcheckade grenen"
-#: gitk:7747
+#: gitk:7828
#, tcl-format
msgid ""
"The commits on branch %s aren't on any other branch.\n"
@@ -749,16 +787,16 @@ msgstr ""
"Incheckningarna på grenen %s existerar inte på någon annan gren.\n"
"Vill du verkligen ta bort grenen %s?"
-#: gitk:7778
+#: gitk:7859
#, tcl-format
msgid "Tags and heads: %s"
msgstr "Taggar och huvuden: %s"
-#: gitk:7792
+#: gitk:7873
msgid "Filter"
msgstr "Filter"
-#: gitk:8086
+#: gitk:8167
msgid ""
"Error reading commit topology information; branch and preceding/following "
"tag information will be incomplete."
@@ -766,125 +804,125 @@ msgstr ""
"Fel vid läsning av information om incheckningstopologi; information om "
"grenar och föregående/senare taggar kommer inte vara komplett."
-#: gitk:9072
+#: gitk:9153
msgid "Tag"
msgstr "Tagg"
-#: gitk:9072
+#: gitk:9153
msgid "Id"
msgstr "Id"
-#: gitk:9118
+#: gitk:9199
msgid "Gitk font chooser"
msgstr "Teckensnittsväljare för Gitk"
-#: gitk:9135
+#: gitk:9216
msgid "B"
msgstr "F"
-#: gitk:9138
+#: gitk:9219
msgid "I"
msgstr "K"
-#: gitk:9231
+#: gitk:9312
msgid "Gitk preferences"
msgstr "Inställningar för Gitk"
-#: gitk:9232
+#: gitk:9313
msgid "Commit list display options"
msgstr "Alternativ för incheckningslistvy"
-#: gitk:9235
+#: gitk:9316
msgid "Maximum graph width (lines)"
msgstr "Maximal grafbredd (rader)"
-#: gitk:9239
+#: gitk:9320
#, tcl-format
msgid "Maximum graph width (% of pane)"
msgstr "Maximal grafbredd (% av ruta)"
-#: gitk:9244
+#: gitk:9325
msgid "Show local changes"
msgstr "Visa lokala ändringar"
-#: gitk:9249
+#: gitk:9330
msgid "Auto-select SHA1"
msgstr "Välj SHA1 automatiskt"
-#: gitk:9254
+#: gitk:9335
msgid "Diff display options"
msgstr "Alternativ för diffvy"
-#: gitk:9256
+#: gitk:9337
msgid "Tab spacing"
msgstr "Blanksteg för tabulatortecken"
-#: gitk:9260
+#: gitk:9341
msgid "Display nearby tags"
msgstr "Visa närliggande taggar"
-#: gitk:9265
+#: gitk:9346
msgid "Limit diffs to listed paths"
msgstr "Begränsa diff till listade sökvägar"
-#: gitk:9272
+#: gitk:9353
msgid "External diff tool"
msgstr "Externt diff-verktyg"
-#: gitk:9274
+#: gitk:9355
msgid "Choose..."
msgstr "Välj..."
-#: gitk:9279
+#: gitk:9360
msgid "Colors: press to choose"
msgstr "Färger: tryck för att välja"
-#: gitk:9282
+#: gitk:9363
msgid "Background"
msgstr "Bakgrund"
-#: gitk:9286
+#: gitk:9367
msgid "Foreground"
msgstr "Förgrund"
-#: gitk:9290
+#: gitk:9371
msgid "Diff: old lines"
msgstr "Diff: gamla rader"
-#: gitk:9295
+#: gitk:9376
msgid "Diff: new lines"
msgstr "Diff: nya rader"
-#: gitk:9300
+#: gitk:9381
msgid "Diff: hunk header"
msgstr "Diff: delhuvud"
-#: gitk:9306
+#: gitk:9387
msgid "Select bg"
msgstr "Markerad bakgrund"
-#: gitk:9310
+#: gitk:9391
msgid "Fonts: press to choose"
msgstr "Teckensnitt: tryck för att välja"
-#: gitk:9312
+#: gitk:9393
msgid "Main font"
msgstr "Huvudteckensnitt"
-#: gitk:9313
+#: gitk:9394
msgid "Diff display font"
msgstr "Teckensnitt för diffvisning"
-#: gitk:9314
+#: gitk:9395
msgid "User interface font"
msgstr "Teckensnitt för användargränssnitt"
-#: gitk:9339
+#: gitk:9420
#, tcl-format
msgid "Gitk: choose color for %s"
msgstr "Gitk: välj färg för %s"
-#: gitk:9720
+#: gitk:9801
msgid ""
"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
" Gitk requires at least Tcl/Tk 8.4."
@@ -892,24 +930,24 @@ msgstr ""
"Gitk kan tyvärr inte köra med denna version av Tcl/Tk.\n"
" Gitk kräver åtminstone Tcl/Tk 8.4."
-#: gitk:9812
+#: gitk:9900
msgid "Cannot find a git repository here."
msgstr "Hittar inget gitk-arkiv här."
-#: gitk:9816
+#: gitk:9904
#, tcl-format
msgid "Cannot find the git directory \"%s\"."
msgstr "Hittar inte git-katalogen \"%s\"."
-#: gitk:9853
+#: gitk:9951
#, tcl-format
msgid "Ambiguous argument '%s': both revision and filename"
msgstr "Tvetydigt argument \"%s\": både revision och filnamn"
-#: gitk:9865
+#: gitk:9963
msgid "Bad arguments to gitk:"
msgstr "Felaktiga argument till gitk:"
-#: gitk:9925
+#: gitk:10023
msgid "Command line"
msgstr "Kommandorad"
--
1.6.0.2.GIT
^ permalink raw reply related
* Re: [PATCH 1/3] Prepare for non-interactive merge-preserving rebase
From: Johannes Sixt @ 2008-09-24 6:17 UTC (permalink / raw)
To: SZEDER Gábor
Cc: Andreas Ericsson, Stephen Haberman, Git Mailing List,
Junio C Hamano
In-Reply-To: <20080924001027.GA19264@neumann>
SZEDER Gábor schrieb:
> -A---B master
> \
> C---M topic
> \ /
> D
...
> If I now execute 'git rebase -p master topic', I get the following:
>
> -A---B master
> \ \
> \ C'---M' topic
> \ /
> C----D
>
> But I would rather like to have the following:
>
> -A---B master
> \
> C'---M' topic
> \ /
> D'
>
> Would such a behaviour possible at all?
I think that rebase -i -p was meant to deal only with the situation where
the merged-in branch is from outside the topic branch. What you want is
called "git-sequencer". Search the archives.
-- Hannes
^ permalink raw reply
* [PATCH] maint: check return of split_cmdline to avoid bad config strings
From: Deskin Miller @ 2008-09-24 6:10 UTC (permalink / raw)
To: git; +Cc: gitster
>From 7679d395856d17d7853eea0fc196435eab9be08f Mon Sep 17 00:00:00 2001
From: Deskin Miller <deskinm@umich.edu>
Date: Mon, 22 Sep 2008 11:06:41 -0400
Subject: [PATCH] maint: check return of split_cmdline to avoid bad config strings
Signed-off-by: Deskin Miller <deskinm@umich.edu>
---
As the testcase demonstrates, it's possible to have split_cmdline return -1 and
deallocate any memory it's allocated, if the config string is missing an end
quote. In both the cases below, the return isn't checked, causing a pretty
immediate segfault.
builtin-merge.c | 2 ++
git.c | 2 ++
t/t1300-repo-config.sh | 10 ++++++++++
3 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/builtin-merge.c b/builtin-merge.c
index b280444..dcaf368 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -442,6 +442,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
buf = xstrdup(v);
argc = split_cmdline(buf, &argv);
+ if (argc < 0)
+ die("Bad branch.%s.mergeoptions string", branch);
argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
argc++;
diff --git a/git.c b/git.c
index fdb0f71..5582c51 100644
--- a/git.c
+++ b/git.c
@@ -162,6 +162,8 @@ static int handle_alias(int *argcp, const char ***argv)
alias_string + 1, alias_command);
}
count = split_cmdline(alias_string, &new_argv);
+ if (count < 0)
+ die("Bad alias.%s string", alias_command);
option_count = handle_options(&new_argv, &count, &envchanged);
if (envchanged)
die("alias '%s' changes environment variables\n"
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 64567fb..3794d23 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -741,4 +741,14 @@ test_expect_success 'symlinked configuration' '
'
+test_expect_success 'check split_cmdline return' "
+ git config alias.split-cmdline-fix 'echo \"' &&
+ git split-cmdline-fix || test \$? = 128 &&
+ echo foo > foo &&
+ git add foo &&
+ git commit -m 'initial commit' &&
+ git config branch.master.mergeoptions 'echo \"' &&
+ git merge master || test \$? = 128
+ "
+
test_done
--
1.6.0.2.GIT
^ permalink raw reply related
* Re: Locking binary files
From: Daniel Barkalow @ 2008-09-24 4:15 UTC (permalink / raw)
To: Dmitry Potapov
Cc: Junio C Hamano, Mario Pareja, Andreas Ericsson, Git Mailing List
In-Reply-To: <20080923232154.GW21650@dpotapov.dyndns.org>
On Wed, 24 Sep 2008, Dmitry Potapov wrote:
> On Tue, Sep 23, 2008 at 06:29:53PM -0400, Daniel Barkalow wrote:
> > On Wed, 24 Sep 2008, Dmitry Potapov wrote:
> >
> > > It still will happen if developers work on topic branches, and it is not
> > > a rate situation with Git. Thus locking some particular path is stupid.
> > > What you may want instead is too mark SHA-1 of this file as being edited
> > > and later maybe as being replaced with another one. In this case, anyone
> > > who has the access to the central information storage will get warning
> > > about attempt to edit a file that is edited or already replaced with a
> > > new version.
> >
> > No, your goal is to avoid having to do a merge in order to do a particular
> > push. That push is the push to the shared location. It doesn't matter if
> > you use topic branches, because your eventual goal is still to push to the
> > shared location (or, possibly, to have the project maintainer push to the
> > shared location with some sort of interesting delegation), so you lock the
> > shared location, not your topic branch.
>
> What are you saying is that when I am locking some file on the current
> branch, Git (or whatever script that performs this locking) should figure
> out what is the original shared branch for it and lock the file there.
Or you should have to say. But "git lock <filename>" should probably
put the lock on whatever branch "git push" would push to, and similarly
for the other argument combinations that "git push" permits.
> When you have finished to edit and push changes then the lock should be
> removed if changes are pushed to this shared branch, otherwise it should
> be some token of delegation to the project maintainer who is going to
> push (or probably first merge, because other files may need that) to
> this branch.
Correct.
> Maybe, it can work, but it sounds too complex to me. I believe that my
> idea using SHA-1 is better. After all, what is file? It is its content.
> At least, in Git, we always identify files by their content.
Not at all; there are plenty of cases where what matters is the path, and
some things are relevant by virtue of the form of the filename which names
that content.
> Thus if you lock some file, you put a lock on certain SHA-1. Now,
> regardless of branches and paths, this lock can work provided that you
> have access to some shared location. Of course, this lock is purely
> advisory, but it is good, because you may want to ignore it in some
> case.
In my design, the lock (on the shared repository) is not advisory; if
someone else has it, you can't push if the new commit doesn't match the
old commit for that path. (Of course, the system might let you break the
other person's lock.) I don't think locks are particularly useful if you
don't get some particular guarantee out ofhaving them (in my case, that
somebody else will have to do any merge for the file if one is needed).
> For instance, you want to created a new branch based on the
> current shared location and have no plan to ever merge it back. In this
> case, the lock on the shared branch should not matter to you. This is
> true regardless how you implement locking, and in your scheme it will
> another special case.
If you have no intention to merge a local branch back to the remote branch
it is based on, then you won't have the remote configured for this. If the
locking and lock-checking code uses the push configuration to determine
what locks make sense, it'll automatically be unrelated.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* [RFC PATCH v2] fetch-pack: log(n)-transmission find_common()
From: Thomas Rast @ 2008-09-24 0:48 UTC (permalink / raw)
To: git; +Cc: Clemens Buchacher
In-Reply-To: <1221692484-21977-1-git-send-email-trast@student.ethz.ch>
Replaces the existing simple history search with a more sophisticated
algorithm:
1) Walk history with exponentially increasing stride lengths; i.e.,
send the 1st commit, then the 2nd after that, then the 4th after
that, and so on.
2) Bisect the resulting intervals.
Combined with tracking the "outstanding haves" so that we can detect
which sha1s were never ACKed by upload-pack (and hence not common),
this gives O(log(n)) required "have" lines.
Unfortunately this cannot work if the server sends fake ACKs, so we
introduce a capability 'exp-stride' which instructs upload-pack to
disable ok_to_give_up(). (Which incidentally saves the server a lot
of work.)
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
So, after the resounding success that v1 of this patch was, I went
through and actually made it work, or at least I hope so.
I eventually gave up on trying to understand the exact interaction of
mark_common(), which sometimes pushes, and rev_list_push(), which
sometimes marks, and just rewrote them to each only do one thing. I
also rewrote the old strategy in terms of the new get_rev_stride
(always keeping stride length at 1) because that was far less work
than integrating the existing code with the new one.
For the timings below, I ran the (new) daemon locally, with two repos:
- a 'clone --mirror' of my own git.git, with a branch 'next' 525
commits from the above cc185a6
- a 'clone --mirror' of the completely unrelated adps.git, which
shares no objects with git.git
Some not really statistically sound timings, usually best of 3-5:
## A stripped down git.git, with only one branch and no tags
$ git branch -a
* master
$ git tag
$ git log -1 --pretty=oneline master
cc185a6a8ac24737a26ec4b40cc401c2db8b2e97 Start draft release notes for 1.6.0.3
## I still have the old (dashed) forms in /usr/bin from RPMs
$ /usr/bin/git --version
git version 1.5.6
## (1a) "Updating" from the git.git that is further ahead (OLD)
$ time /usr/bin/git-fetch-pack -k git://localhost/git next
[...]
real 0m1.004s
user 0m0.228s
sys 0m0.028s
## (1b) "Updating" from the git.git that is further ahead (NEW)
$ time git fetch-pack -k git://localhost/git next
[...]
real 0m0.977s
user 0m0.208s
sys 0m0.068s
## (2a) Fetching the unrelated repo from scratch (OLD)
$ time /usr/bin/git-fetch-pack -k git://localhost/adps master
[...]
real 0m9.560s
user 0m0.720s
sys 0m0.128s
## (2b) Fetching the unrelated repo from scratch (NEW)
$ time git fetch-pack -k git://localhost/adps master
[...]
real 0m0.596s
user 0m0.372s
sys 0m0.008s
## (3a) Fetching over the network from real repo (OLD)
$ time /usr/bin/git-fetch-pack git://git.kernel.org/pub/scm/git/git.git next
[...]
user 0m0.528s
sys 0m0.136s
## (3b) Fetching over the network from real repo (NEW)
$ time git fetch-pack git://git.kernel.org/pub/scm/git/git.git next
[...]
user 0m0.540s
sys 0m0.180s
## Add more refs to make it more interesting
$ git remote add origin ~/dev/git
$ git fetch --tags origin
## (4a) like 1a, but with lots of tags
$ time /usr/bin/git-fetch-pack -k git://localhost/git next
[...]
real 0m1.075s
user 0m0.452s
sys 0m0.048s
## (4b) like 1b, but with lots of tags
$ time git fetch-pack -k git://localhost/git next
[...]
real 0m0.837s
user 0m0.236s
sys 0m0.040s
Clearly, this approach does solve the issue I mentioned in the
motivation earlier in the thread, where the initial fetch of
completely disjoint repositories takes _ages_. Somewhat to my own
surprise, it seems to do quite well in _all_ cases even though it
aggressively digs through history.
Note, however, that the timings aren't really solid; the final write
of the pack, which I assume is fsync()ed, seems to have a big impact
on the execution time. Test (3) obviously depends more on network
performance than anything else; and it uses the old (linear)
algorithm, but in the new implementation.
I'd appreciate testers and eyeballs on the patch. I'll think about
the ref heads "reduced DAG" again, to possibly shave off some more
(client side cpu) time when I get the time, but that likely won't be
in the next few days.
- Thomas
PS: Thanks drizzd for the discussion of the topic on IRC.
PPS: Junio, enjoy your holidays :-)
builtin-fetch-pack.c | 477 +++++++++++++++++++++++++++++++++++++++++---------
upload-pack.c | 7 +-
2 files changed, 400 insertions(+), 84 deletions(-)
diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 4dfef29..721fe08 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -25,6 +25,12 @@ static const char fetch_pack_usage[] =
#define COMMON_REF (1U << 2)
#define SEEN (1U << 3)
#define POPPED (1U << 4)
+#define BISECTED_FW (1U << 5)
+#define BISECTED_BW (1U << 6)
+#define NOTCOMMON (1U << 7)
+#define HAS_INFO (1U << 8)
+#define CLEAN_MARKS (COMMON | COMMON_REF | SEEN | POPPED | BISECTED_FW \
+ | BISECTED_BW | NOTCOMMON)
static int marked;
@@ -34,133 +40,412 @@ static int marked;
*/
#define MAX_IN_VAIN 256
-static struct commit_list *rev_list;
-static int non_common_revs, multi_ack, use_sideband;
+struct work_list
+{
+ struct work_list *next;
+ struct commit *commit;
+ unsigned int stride; /* current stride length between commits */
+ unsigned int steps; /* steps left to go before emitting again */
+ unsigned int depth; /* sideline depth */
+ unsigned int bisect;
+};
+
+/* "recursion stack" of our strategy of choosing sha1s to transmit */
+static struct work_list *work_list = NULL;
-static void rev_list_push(struct commit *commit, int mark)
+/* list of commits not ACKed yet */
+static struct commit_list *outstanding = NULL;
+static struct commit_list *outstanding_end = NULL;
+
+struct commit_info
{
- if (!(commit->object.flags & mark)) {
- commit->object.flags |= mark;
+ struct commit_list *children;
+};
- if (!(commit->object.parsed))
- if (parse_commit(commit))
- return;
- insert_by_date(commit, &rev_list);
+static int non_common_revs = 1, multi_ack, use_sideband, exp_stride_algorithm;
- if (!(commit->object.flags & COMMON))
- non_common_revs++;
+static struct commit_info *get_commit_info(struct commit *commit)
+{
+ if (commit->object.flags & HAS_INFO)
+ return commit->util;
+
+ struct commit_info *info = xmalloc(sizeof(struct commit_info));
+ info->children = NULL;
+ commit->util = info;
+ commit->object.flags |= HAS_INFO;
+ return info;
+}
+
+static void work_list_insert(struct work_list *work_item)
+{
+ struct work_list **pp = &work_list;
+ struct work_list *p;
+
+ while ((p = *pp)) {
+ if (p->bisect || work_item->bisect) {
+ if (p->bisect > work_item->bisect)
+ break;
+ } else {
+ if (p->depth > work_item->depth)
+ break;
+ else if (p->commit->date < work_item->commit->date)
+ break;
+ }
+
+ pp = &p->next;
}
+
+ work_item->next = p;
+ *pp = work_item;
}
-static int rev_list_insert_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static void add_child(struct commit *parent, struct commit *child)
+{
+ struct commit_info *info = get_commit_info(parent);
+ struct commit_list *item;
+ for (item = info->children; item; item = item->next)
+ if (item->item == child)
+ break;
+ if (!item)
+ commit_list_insert(child, &(info->children));
+}
+
+
+/*
+ Marks all (known) children of this commit NOTCOMMON. We call this
+ for all sha1s the server did not ACK.
+*/
+
+static void mark_not_common(struct commit *commit)
+{
+ struct commit_info *info = get_commit_info(commit);
+ struct commit_list *child;
+
+ assert(!(commit->object.flags & COMMON));
+
+ if (commit->object.flags & NOTCOMMON)
+ return;
+
+ commit->object.flags |= NOTCOMMON;
+
+ for (child = info->children; child; child = child->next)
+ mark_not_common(child->item);
+}
+
+
+static void check_parsed_and_mark(struct commit *commit)
+{
+ struct commit_list *parent;
+
+ if (!commit && commit->object.parsed)
+ return;
+
+ parse_commit(commit);
+
+ for (parent = commit->parents; parent; parent = parent->next) {
+ add_child(parent->item, commit);
+ if (parent->item->object.flags & NOTCOMMON)
+ mark_not_common(commit);
+ }
+}
+
+
+static void rev_list_push(struct commit *commit, unsigned int stride,
+ unsigned int steps, unsigned int depth)
+{
+ struct work_list *work_item;
+
+ check_parsed_and_mark(commit);
+
+ work_item = xmalloc(sizeof(struct work_list));
+ work_item->commit = commit;
+ work_item->stride = stride;
+ work_item->steps = steps;
+ work_item->depth = depth;
+ work_item->bisect = 0;
+ work_list_insert(work_item);
+}
+
+static int rev_list_insert_ref(const char *path, const unsigned char *sha1,
+ int flag, void *cb_data)
{
struct object *o = deref_tag(parse_object(sha1), path, 0);
- if (o && o->type == OBJ_COMMIT)
- rev_list_push((struct commit *)o, SEEN);
+ if (o && o->type == OBJ_COMMIT && !(o->flags & SEEN))
+ rev_list_push((struct commit *)o, 1, 1, 0);
return 0;
}
-static int clear_marks(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static int clear_marks(const char *path, const unsigned char *sha1, int flag,
+ void *cb_data)
{
struct object *o = deref_tag(parse_object(sha1), path, 0);
if (o && o->type == OBJ_COMMIT)
- clear_commit_marks((struct commit *)o,
- COMMON | COMMON_REF | SEEN | POPPED);
+ clear_commit_marks((struct commit *)o, CLEAN_MARKS);
return 0;
}
+
/*
- This function marks a rev and its ancestors as common.
- In some cases, it is desirable to mark only the ancestors (for example
- when only the server does not yet know that they are common).
+ Mark commits backwards through history as COMMON.
*/
-static void mark_common(struct commit *commit,
- int ancestors_only, int dont_parse)
+static void mark_common(struct commit *commit, int ancestors_only, int dont_parse)
{
- if (commit != NULL && !(commit->object.flags & COMMON)) {
- struct object *o = (struct object *)commit;
+ struct commit_list *parents;
+ struct object *o;
- if (!ancestors_only)
- o->flags |= COMMON;
+ if (commit == NULL || commit->object.flags & (COMMON_REF|COMMON))
+ return;
- if (!(o->flags & SEEN))
- rev_list_push(commit, SEEN);
- else {
- struct commit_list *parents;
-
- if (!ancestors_only && !(o->flags & POPPED))
- non_common_revs--;
- if (!o->parsed && !dont_parse)
- if (parse_commit(commit))
- return;
-
- for (parents = commit->parents;
- parents;
- parents = parents->next)
- mark_common(parents->item, 0, dont_parse);
- }
+ if (!dont_parse && !(commit->object.parsed))
+ check_parsed_and_mark(commit);
+
+ o = (struct object *)commit;
+
+ if (!ancestors_only)
+ o->flags |= COMMON;
+
+ for (parents = commit->parents; parents; parents = parents->next) {
+ add_child(parents->item, commit);
+ mark_common(parents->item, 0, dont_parse);
}
}
+
+
/*
- Get the next rev to send, ignoring the common.
+ Queue all revs in the list for simple backward search. Does not
+ requeue already SEEN commits.
*/
-static const unsigned char* get_rev(void)
+static void queue_list(struct commit *child, struct commit_list *list,
+ unsigned int stride, unsigned int steps,
+ unsigned int depth)
{
- struct commit *commit = NULL;
+ while (list) {
+ add_child(list->item, child);
+ if (!(list->item->object.flags & SEEN))
+ rev_list_push(list->item, stride, steps, depth);
+ list = list->next;
+ }
+}
+
+
+/*
+ Queues a commit for bisection
+*/
+
+static void setup_bisect(struct commit *commit, int depth)
+{
+ struct work_list *work_item = xmalloc(sizeof(struct work_list));
+
+ work_item->commit = commit;
+ work_item->bisect = 1+depth;
+ work_item->depth = 0;
+ work_list_insert(work_item);
+}
+
+
+/*
+ Queues a list of commits for bisection
+*/
+
+static void setup_bisect_all (struct commit_list* list, int depth)
+{
+ while (list) {
+ setup_bisect(list->item, depth);
+ list = list->next;
+ }
+}
+
+
+/*
+ Backwards search. If we use exp_stride_algorithm, it takes
+ exponential strides between commits chosen.
+*/
+
+static struct commit* get_rev_stride(struct work_list *work_item)
+{
+ struct commit *commit = work_item->commit;
+ unsigned int steps = work_item->steps;
+
+ while (steps++ < work_item->stride-1 && commit->parents
+ && !(commit->object.flags & (SEEN|COMMON|COMMON_REF))) {
+ /* all but the first parent line are queued for later */
+ if (commit->parents)
+ queue_list(commit, commit->parents->next,
+ work_item->stride, steps,
+ work_item->depth+1);
+
+ /* follow the first parent line directly */
+ commit->object.flags |= SEEN;
+ add_child(commit->parents->item, commit);
+ commit = commit->parents->item;
+ check_parsed_and_mark(commit);
+ }
+
+ if (commit->object.flags & (SEEN|COMMON)) {
+ /* already been here! */
+ commit = NULL;
+ } else if (commit->object.flags & COMMON_REF) {
+ /* this came from a ref; we stop here, but need to
+ * emit it so the server knows too */
+ commit->object.flags |= POPPED|SEEN|BISECTED_BW;
+ if (exp_stride_algorithm)
+ setup_bisect(commit, 0);
+ } else {
+ /* usual case: this is news to us, so we scan further
+ * back. note that the first-depth bisection only
+ * needs to go forward */
+ commit->object.flags |= POPPED|SEEN|BISECTED_BW;
+ queue_list(commit, commit->parents,
+ exp_stride_algorithm ? work_item->stride*2 : 1,
+ 0, work_item->depth);
+ if (exp_stride_algorithm)
+ setup_bisect(commit, 0);
+ }
+
+ free(work_item);
+
+ return commit;
+}
- while (commit == NULL) {
- unsigned int mark;
- struct commit_list *parents;
- if (rev_list == NULL || non_common_revs == 0)
+/*
+ Bisection state of the exponential stride algorithm: scans forward
+ (backward) for a non-common/already-sent (common/already-sent,
+ resp.) commit, then emits the middle of that range, and re-queues.
+
+ This means we bisect the discovered range in log(n) transmissions,
+ although we do make O(n) steps through history.
+*/
+
+static struct commit* get_rev_bisect(struct work_list *work_item)
+{
+ struct commit *full;
+ struct commit *half;
+ int half_step;
+ struct commit_info *info;
+ unsigned int flags = work_item->commit->object.flags;
+
+ if (!(flags & (COMMON|BISECTED_BW))) {
+ /* We don't know anything about the history _backward_
+ * from this, so search it */
+
+ full = work_item->commit;
+ full->object.flags |= BISECTED_BW;
+ half = work_item->commit;
+ half_step = 0;
+
+ while (full && full->parents) {
+ full = full->parents->item;
+ half_step ^= 1;
+ if (half_step)
+ half = half->parents->item;
+ if (full->object.flags & (POPPED|COMMON))
+ break;
+ }
+
+ /* also insert the same bisection again so we can try
+ * forward too */
+ work_list_insert(work_item);
+
+ if (full->object.flags & POPPED
+ && !(full->object.flags & NOTCOMMON)
+ && !(half->object.flags & (COMMON|POPPED))) {
+ setup_bisect(half, work_item->bisect);
+ half->object.flags |= POPPED;
+ return half;
+ } else {
return NULL;
+ }
+ }
- commit = rev_list->item;
- if (!commit->object.parsed)
- parse_commit(commit);
- parents = commit->parents;
-
- commit->object.flags |= POPPED;
- if (!(commit->object.flags & COMMON))
- non_common_revs--;
-
- if (commit->object.flags & COMMON) {
- /* do not send "have", and ignore ancestors */
- commit = NULL;
- mark = COMMON | SEEN;
- } else if (commit->object.flags & COMMON_REF)
- /* send "have", and ignore ancestors */
- mark = COMMON | SEEN;
- else
- /* send "have", also for its ancestors */
- mark = SEEN;
-
- while (parents) {
- if (!(parents->item->object.flags & SEEN))
- rev_list_push(parents->item, mark);
- if (mark & COMMON)
- mark_common(parents->item, 1, 0);
- parents = parents->next;
+ if (!(flags & (NOTCOMMON|BISECTED_FW))) {
+ /* We don't know anything about the history _forward_
+ * from this, so search it */
+
+ full = work_item->commit;
+ full->object.flags |= BISECTED_FW;
+ half = work_item->commit;
+ half_step = 0;
+
+ while (full && (info=get_commit_info(full))->children) {
+ setup_bisect_all(info->children->next, work_item->bisect);
+ full = info->children->item;
+ half_step ^= 1;
+ if (half_step) {
+ info = get_commit_info(half);
+ half = info->children->item;
+ }
+ if (full->object.flags & (POPPED|NOTCOMMON))
+ break;
}
- rev_list = rev_list->next;
+ if (full->object.flags & POPPED
+ && !(full->object.flags & COMMON)
+ && !(half->object.flags & (NOTCOMMON|POPPED))) {
+ setup_bisect(half, work_item->bisect);
+ half->object.flags |= POPPED;
+ free(work_item);
+ return half;
+ }
}
- return commit->object.sha1;
+ free(work_item);
+ return NULL;
}
+
+/*
+ Get the next revision to send.
+*/
+
+static struct commit *get_rev(void)
+{
+ struct commit *commit = NULL;
+
+ while (commit == NULL && work_list) {
+ struct work_list *work_item = NULL;
+
+ work_item = work_list;
+ /* we update the pointer early so the get_rev
+ * functions can free() or reuse the work_item as
+ * required */
+ work_list = work_item->next;
+
+ commit = work_item->commit;
+
+ check_parsed_and_mark(commit);
+
+ if (work_item->bisect) {
+ commit = get_rev_bisect(work_item);
+ } else {
+ commit = get_rev_stride(work_item);
+ }
+ }
+
+ return commit;
+}
+
+static void pop_outstanding()
+{
+ struct commit_list *item = outstanding;
+ outstanding = item->next;
+ free(item);
+}
+
+
static int find_common(int fd[2], unsigned char *result_sha1,
struct ref *refs)
{
int fetching;
int count = 0, flushes = 0, retval;
+ struct commit *commit;
const unsigned char *sha1;
unsigned in_vain = 0;
int got_continue = 0;
@@ -192,7 +477,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
}
if (!fetching)
- packet_write(fd[1], "want %s%s%s%s%s%s%s%s\n",
+ packet_write(fd[1], "want %s%s%s%s%s%s%s%s%s\n",
sha1_to_hex(remote),
(multi_ack ? " multi_ack" : ""),
(use_sideband == 2 ? " side-band-64k" : ""),
@@ -200,6 +485,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
(args.use_thin_pack ? " thin-pack" : ""),
(args.no_progress ? " no-progress" : ""),
(args.include_tag ? " include-tag" : ""),
+ (exp_stride_algorithm ? " exp-stride" : ""),
" ofs-delta");
else
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
@@ -243,13 +529,25 @@ static int find_common(int fd[2], unsigned char *result_sha1,
flushes = 0;
retval = -1;
- while ((sha1 = get_rev())) {
+ while ((commit = get_rev())) {
+ sha1 = commit->object.sha1;
packet_write(fd[1], "have %s\n", sha1_to_hex(sha1));
if (args.verbose)
fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
in_vain++;
+
+ if (outstanding) {
+ commit_list_insert(commit, &(outstanding_end->next));
+ outstanding_end = outstanding_end->next;
+ } else {
+ commit_list_insert(commit, &outstanding);
+ outstanding_end = outstanding;
+ }
+
if (!(31 & ++count)) {
int ack;
+ int unwound = 0;
+ struct commit_list *item;
packet_flush(fd[1]);
flushes++;
@@ -274,12 +572,23 @@ static int find_common(int fd[2], unsigned char *result_sha1,
} else if (ack == 2) {
struct commit *commit =
lookup_commit(result_sha1);
+ while (commit != outstanding->item) {
+ mark_not_common(outstanding->item);
+ pop_outstanding();
+ unwound++;
+ }
+ pop_outstanding();
+ unwound++;
mark_common(commit, 0, 1);
retval = 0;
in_vain = 0;
got_continue = 1;
}
} while (ack);
+ while (unwound++ < 32) {
+ mark_not_common(outstanding->item);
+ pop_outstanding();
+ }
flushes--;
if (got_continue && MAX_IN_VAIN < in_vain) {
if (args.verbose)
@@ -445,9 +754,8 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
continue;
if (!(o->flags & SEEN)) {
- rev_list_push((struct commit *)o, COMMON_REF | SEEN);
-
- mark_common((struct commit *)o, 1, 1);
+ rev_list_push((struct commit *)o, 1, 0, 0);
+ o->flags |= COMMON_REF;
}
}
@@ -597,6 +905,11 @@ static struct ref *do_fetch_pack(int fd[2],
fprintf(stderr, "Server supports side-band\n");
use_sideband = 1;
}
+ if (server_supports("exp-stride")) {
+ if (args.verbose)
+ fprintf(stderr, "Server supports exp-stride\n");
+ exp_stride_algorithm = 1;
+ }
if (everything_local(&ref, nr_match, match)) {
packet_flush(fd[1]);
goto all_done;
diff --git a/upload-pack.c b/upload-pack.c
index e5adbc0..14012ee 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -37,6 +37,7 @@ static unsigned int timeout;
*/
static int use_sideband;
static int debug_fd;
+static int exp_stride_algorithm;
static void reset_timeout(void)
{
@@ -414,7 +415,7 @@ static int get_common_commits(void)
if (!prefixcmp(line, "have ")) {
switch (got_sha1(line+5, sha1)) {
case -1: /* they have what we do not */
- if (multi_ack && ok_to_give_up())
+ if (multi_ack && !exp_stride_algorithm && ok_to_give_up())
packet_write(1, "ACK %s continue\n",
sha1_to_hex(sha1));
break;
@@ -501,6 +502,8 @@ static void receive_needs(void)
no_progress = 1;
if (strstr(line+45, "include-tag"))
use_include_tag = 1;
+ if (strstr(line+45, "exp-stride"))
+ exp_stride_algorithm = 1;
/* We have sent all our refs already, and the other end
* should have chosen out of them; otherwise they are
@@ -573,7 +576,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
{
static const char *capabilities = "multi_ack thin-pack side-band"
" side-band-64k ofs-delta shallow no-progress"
- " include-tag";
+ " include-tag exp-stride";
struct object *o = parse_object(sha1);
if (!o)
--
tg: (1293c95..) t/fetch-pack-speedup (depends on: origin/master)
^ 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