* Re: [PATCH] git mv: Support moving submodules
From: Junio C Hamano @ 2008-09-12 22:19 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20080912214129.14829.53058.stgit@localhost>
Petr Baudis <pasky@suse.cz> writes:
> diff --git a/builtin-mv.c b/builtin-mv.c
> index 4f65b5a..2970acc 100644
> --- a/builtin-mv.c
> +++ b/builtin-mv.c
> @@ -9,6 +9,7 @@
> #include "cache-tree.h"
> #include "string-list.h"
> #include "parse-options.h"
> +#include "submodule.h"
>
> static const char * const builtin_mv_usage[] = {
> "git mv [options] <source>... <destination>",
> @@ -49,6 +50,24 @@ static const char *add_slash(const char *path)
> return path;
> }
>
> +static int ce_is_gitlink(int i)
> +{
> + return i < 0 ? 0 : S_ISGITLINK(active_cache[i]->ce_mode);
> +}
This interface itself is ugly (why should a caller pass "it is unmerged or
does not exist" without checking?), and it also makes the hunk that begins
at 84/105 ugly. Why not "path_is_gitlink(const char*)" and run
cache_name_pos() here instead?
The interface, even if it is internal, should be done with a better taste
than that, even though I understand that you wanted to reuse the cache_pos
for the source one while you check.
Oh, by the way, what should happen when you have an unmerged path in the
index and say "git mv path elsewhere" (this question is *not* limited to
submodules). Compared to that, what _does_ happen with the current code,
and with your patch?
^ permalink raw reply
* Re: [PATCH 2/6] git rm: Support for removing submodules
From: Petr Baudis @ 2008-09-12 22:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8wtxniez.fsf@gitster.siamese.dyndns.org>
I will collect your feedback on the whole series, then resend it from
scratch - sounds good?
On Fri, Sep 12, 2008 at 02:49:56PM -0700, Junio C Hamano wrote:
> Petr Baudis <pasky@suse.cz> writes:
>
> > @@ -20,7 +20,8 @@ and no updates to their contents can be staged in the index,
> > though that default behavior can be overridden with the `-f` option.
> > When '--cached' is given, the staged content has to
> > match either the tip of the branch or the file on disk,
> > -allowing the file to be removed from just the index.
> > +allowing the file to be removed from just the index;
> > +this is always the case when removing submodules.
>
> Sorry, I read this three times but "this" is unclear to me. Different and
> mutually incompatible interpretations I tried to understand it are:
>
> (1) When removing submodules, whether --cached or not, the index can
> match either HEAD or the work tree; this is different from removing
> regular blobs where the index must match with HEAD without --cached
> nor -f;
>
> (2) When removing submodules with --cached, the index can match either
> HEAD or the work tree and it is removed only from the index. You
> cannot remove submodules without --cached;
>
> (3) When removing submodules, the index can match either HEAD or the work
> tree and it is removed only from the index, even if you did not give
> --cached;
>
> It later becomes clear that you meant (3) in the second hunk, but the
> first time reader of the resulting document (not this patch) won't be
> reading from bottom to top.
>
> This is a leftover issue from ealier documentation 25dc720 (Clarify and
> fix English in "git-rm" documentation, 2008-04-16), but the description is
> unclear what should happen while working towards the initial commit
> (i.e. no HEAD yet). I think check_local_mod() allows removal in such a
> case. Perhaps you can clarify the point while at it, please?
I will have a look.
> > diff --git a/builtin-rm.c b/builtin-rm.c
> > index 6bd8211..7475de2 100644
> > --- a/builtin-rm.c
> > +++ b/builtin-rm.c
> > ...
> > -static void add_list(const char *name)
> > +static void add_list(const char *name, int is_gitlink)
> > {
> > if (list.nr >= list.alloc) {
> > list.alloc = alloc_nr(list.alloc);
> > - list.name = xrealloc(list.name, list.alloc * sizeof(const char *));
> > + list.info = xrealloc(list.info, list.alloc * sizeof(*list.info));
> > }
>
> ALLOC_GROW()?
Neat thing!
> > @@ -38,6 +44,13 @@ static int remove_file(const char *name)
> > if (ret && errno == ENOENT)
> > /* The user has removed it from the filesystem by hand */
> > ret = errno = 0;
> > + if (ret && errno == EISDIR) {
> > + /* This is a gitlink entry; try to remove at least the
> > + * directory if the submodule is not checked out; we always
> > + * leave the checked out ones as they are */
>
> /*
> * Style?
> * for a multi-line comment.
> */
Right - I will have to get used to this. ;-)
> > +static void remove_submodule(const char *name)
> > +{
> > + char *key = submodule_by_path(name);
> > + char *sectend = strrchr(key, '.');
> > +
> > + assert(sectend);
> > + *sectend = 0;
>
> Here is one caller I questioned in my comments on [1/6]. It is clear this
> caller wants to use "submodule.xyzzy" out of "submodule.xyzzy.path". The
> function returning "submodule.xyzzy.path" does not feel like a clean and
> reusable interface to me. I'd suggest either returning "submodule.xyzzy"
> (that's too specialized only for this caller to my taste, though), or just
> "xyzzy" and have the caller synthesize whatever string it wants to use
> (yes, it loses microoptimization but do we really care about it in this
> codepath?), if you have other callers that want different strings around
> "xyzzy".
This is still easier to use than explicit snprintf(), but in the long
run, you're right that returning just the submodule name is the right
thing. I will change the API.
> > @@ -140,7 +169,7 @@ static struct option builtin_rm_options[] = {
> >
> > int cmd_rm(int argc, const char **argv, const char *prefix)
> > {
> > - int i, newfd;
> > + int i, newfd, subs;
>
> Perhaps hoist "int removed" up one scope level and reuse it? I misread
> that you are counting the number of gitlinks in the index, not the number
> of gitlinks that is being removed, on my first read. The variable is used
> for the latter.
Sensible idea.
On Fri, Sep 12, 2008 at 02:59:12PM -0700, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
> >> +{
> >> + char *key = submodule_by_path(name);
> >> + char *sectend = strrchr(key, '.');
> >> +
> >> + assert(sectend);
> >> + *sectend = 0;
> >
> > Here is one caller I questioned in my comments on [1/6]...
>
> Another thing --- can submodule_by_path() ever return NULL saying "I do
> not see one in the configuration"?
No, it would rather die().
--
Petr "Pasky" Baudis
The next generation of interesting software will be done
on the Macintosh, not the IBM PC. -- Bill Gates
^ permalink raw reply
* Re: [PATCH 2/6] git rm: Support for removing submodules
From: Junio C Hamano @ 2008-09-12 22:42 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20080912222429.GE10360@machine.or.cz>
Petr Baudis <pasky@suse.cz> writes:
>> >> +{
>> >> + char *key = submodule_by_path(name);
>> >> + char *sectend = strrchr(key, '.');
>> >> +
>> >> + assert(sectend);
>> >> + *sectend = 0;
>> >
>> > Here is one caller I questioned in my comments on [1/6]...
>>
>> Another thing --- can submodule_by_path() ever return NULL saying "I do
>> not see one in the configuration"?
>
> No, it would rather die().
Hmmmm. If I did...
$ git init
$ create and add normal paths
$ git clone git://..../gitk.git gitk
$ git add gitk
: heh, I changed my mind
$ git rm gitk
the last step would die, because I changed my mind before fully
initializing gitk repository as a proper submodule?
How would I get rid of the index entry to recover from the mistake?
$ rm -fr gitk
$ git rm gitk
would presumably fail the same way, no? I hope I am misreading the
code...
We need to be extremely careful not to break people who do not (yet) have
[submodule "xyzzy"] entries in config and/or .gitmodules when dealing with
the gitlink entries in the index.
^ permalink raw reply
* Re: CGit and repository list
From: Petr Baudis @ 2008-09-12 22:48 UTC (permalink / raw)
To: Johan Herland; +Cc: git, Lars Hjemli, Jakub Narebski, Kristian H??gsberg
In-Reply-To: <200809121812.40920.johan@herland.net>
[-- Attachment #1: Type: text/plain, Size: 1981 bytes --]
On Fri, Sep 12, 2008 at 06:12:40PM +0200, Johan Herland wrote:
> On Friday 12 September 2008, Lars Hjemli wrote:
> > On Fri, Sep 12, 2008 at 4:58 PM, Petr Baudis <pasky@suse.cz> wrote:
> > > it seems that cgit
> > > requires all the repositories explicitly listed in the config file.
> > > Do you plan to remove this limitation in the future?
> >
> > Not really, I'd rather add another command (or a commandline option)
> > to generate an include-file for cgitrc by scanning directory-trees
> > for git repos. I've CC'd Kristian since I believe he's got such a
> > script running for freedesktop.org; if so, maybe it could be
> > included/used as basis for something similar in cgit?
>
> Here's a script I wrote for locating repos and generating repo
> lists/configs for cgit, gitweb and hgwebdir (yes, this handles hg repos
> as well). It works either as a CGI script (producing a list of detected
> repos in HTML format), or from the command-line. It's only been tested
> on an experimental DVCS server at $dayjob, so you might have to change
> things to make it work in your scenario.
>
> If there is interest in this, I can create a public repo and we can keep
> improving on it.
Thanks. The script was a bit more scary than I thought, but in the end I
managed to generate something. There are trailing dots in project names,
but I'm not going to waste time on that anymore - this has long gone
over the 20 minutes I originally alotted the project anyway; I hope cgit
will gain a builtin capability for this in the future, since this is
still quite a pain. Attached is a random patch for your script I had to
use, FWIW.
Unfortunately, the recommended RewriteRule is not working - it does not
play well together with query parameters cgit is using, so e.g. browsing
past commits does not work. What RewriteRule should I use instead?
--
Petr "Pasky" Baudis
The next generation of interesting software will be done
on the Macintosh, not the IBM PC. -- Bill Gates
[-- Attachment #2: repofinder.diff --]
[-- Type: text/plain, Size: 2107 bytes --]
--- repofinder-orig.py 2008-09-13 00:44:22.000000000 +0200
+++ repofinder.py 2008-09-13 00:44:47.000000000 +0200
@@ -244,7 +244,7 @@
if (self.group):
assert name.startswith(self.group.path)
name = name[len(self.group.path):]
- name = name.strip("/")
+ name = name.strip("/srv/git/")
self._name = self.nameFromPath(name)
return self._name
name = property(getName)
@@ -267,7 +267,10 @@
"""Return a (name, email) tuple with our best guess as to who
owns this repo
"""
- return (self.ownerName, self.ownerEmail)
+ __o = self.ownerName
+ if (__o is None):
+ __o = ''
+ return (__o, self.ownerEmail)
owner = property(getOwner)
def getDescription (self):
@@ -286,14 +289,15 @@
@staticmethod
def nameFromPath (path):
- if path.endswith(".git"): path = path[:-4]
+ if path.endswith(".git"): path = path[:-5]
path = path.rstrip("/")
return path
@staticmethod
def cloneUrlFromPath (path):
if path.endswith("/.git"): path = path[:-5]
- return "ssh://%s%s" % (Settings['ServerName'], path)
+ path = path.strip("/srv/git")
+ return "git://%s/%sgit" % (Settings['ServerName'], path)
def __init__ (self, path):
Repo.__init__(self, path)
@@ -316,6 +320,9 @@
def getOwnerEmail (self):
if self._ownerEmail is None:
self._ownerEmail = self.config.get("user.email")
+ if self._ownerEmail is None:
+ try: self._ownerEmail = open(os.path.join(self.path, "owner")).read().strip()
+ except: pass
return Repo.getOwnerEmail(self)
ownerEmail = property(getOwnerEmail)
@@ -592,12 +599,12 @@
for repo in sorted(group.repos):
url = repo.path
if url.endswith("/.git"): url = url[:-5]
- url = url.strip("/")
+ url = url.strip("/srv/git/")
print >>self.f, "repo.url=%s" % (url)
print >>self.f, "repo.path=%s" % (repo.path)
print >>self.f, "repo.name=%s" % (repo.name)
print >>self.f, "repo.desc=%s" % (repo.description)
- print >>self.f, "repo.owner=%s <%s>" % repo.owner
+ print >>self.f, "repo.owner=%s%s" % repo.owner
print >>self.f, "repo.clone-url=%s" % (repo.clone)
print >>self.f, ""
^ permalink raw reply
* [ANN] mtn2git v0.1
From: Felipe Contreras @ 2008-09-12 22:59 UTC (permalink / raw)
To: git, monotone-devel, devel, openembedded-devel
Hi,
This is the result of various experiments I've been doing while trying
to import mtn repositories into git. I've looked into other mtn2git
scripts but none fitted my needs.
After some rfcs on git and monotone mailing lists it seems now the
script is going in the right direction.
There are two modes:
== checkout ==
In this mode each revision is checked out and imported directly into
git. This means it's 100% sure that the result would be an exact
clone.
The disadvantage is that it's extremely slow (1 day for 25,000 commits).
== fast-import ==
This mode requires a few patches for git fast-import, it's very fast
(40 min for 25,000 commits), but not 100% reliable yet.
There are also some missing features like branch creation and updates.
My plan is to keep these two modes in the code until fast-import
method is reliable enough.
I've tried this with Pidgin's repository. The result is here:
http://github.com/felipec/pidgin-clone
It would be interesting to do something similar with OE's repo. Any takers?
Comments and patches are welcome :)
--
Felipe Contreras
^ permalink raw reply
* Re: CGit and repository list
From: Lars Hjemli @ 2008-09-12 23:20 UTC (permalink / raw)
To: Petr Baudis; +Cc: Johan Herland, git, Jakub Narebski, Kristian Høgsberg
In-Reply-To: <20080912224817.GF10360@machine.or.cz>
On Sat, Sep 13, 2008 at 12:48 AM, Petr Baudis <pasky@suse.cz> wrote:
> On Fri, Sep 12, 2008 at 06:12:40PM +0200, Johan Herland wrote:
>> On Friday 12 September 2008, Lars Hjemli wrote:
>> > On Fri, Sep 12, 2008 at 4:58 PM, Petr Baudis <pasky@suse.cz> wrote:
>> > > it seems that cgit
>> > > requires all the repositories explicitly listed in the config file.
>> > > Do you plan to remove this limitation in the future?
>> >
>> > Not really, I'd rather add another command (or a commandline option)
>> > to generate an include-file for cgitrc by scanning directory-trees
>> > for git repos. I've CC'd Kristian since I believe he's got such a
>> > script running for freedesktop.org; if so, maybe it could be
>> > included/used as basis for something similar in cgit?
>>
>> Here's a script I wrote for locating repos and generating repo
>> lists/configs for cgit, gitweb and hgwebdir (yes, this handles hg repos
>> as well). It works either as a CGI script (producing a list of detected
>> repos in HTML format), or from the command-line. It's only been tested
>> on an experimental DVCS server at $dayjob, so you might have to change
>> things to make it work in your scenario.
>>
>> If there is interest in this, I can create a public repo and we can keep
>> improving on it.
>
> Thanks. The script was a bit more scary than I thought, but in the end I
> managed to generate something. There are trailing dots in project names,
> but I'm not going to waste time on that anymore - this has long gone
> over the 20 minutes I originally alotted the project anyway; I hope cgit
> will gain a builtin capability for this in the future, since this is
> still quite a pain.
I guess I could add support for something like
scan-paths=/pub/git
in cgitrc (and optionally store the result of the scan as another
cgitrc-file in the cache directory). Would that improve things for
you?
> Unfortunately, the recommended RewriteRule is not working - it does not
> play well together with query parameters cgit is using, so e.g. browsing
> past commits does not work. What RewriteRule should I use instead?
On hjemli.net I used to specify "virtual-root=/git" in cgitrc combined
with this rule in /etc/apache/httpd.conf
RewriteRule ^/git/(.*)$ /cgit/cgit.cgi?url=$1 [L,QSA]
But currently I'm running the tip of the wip-branch (which has support
for PATH_INFO) on hjemli.net , so I've removed the "virtual-root" from
cgitrc and the rewriterule from httpd.conf and just use this instead:
ScriptAlias /git /var/www/htdocs/cgit/cgit.cgi
hth,
larsh
^ permalink raw reply
* O(#haves*...) behaviour in "have <sha>" processing in upload-pack
From: Thomas Rast @ 2008-09-13 0:11 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 2899 bytes --]
Hi *
evilchelu (Cristi Balan) pointed out on IRC that 'git fetch' takes a
long time when fetching a history-disjoint repository.
For example,
mkdir test && cd test
git init
git remote add -f paperclip git://github.com/thoughtbot/paperclip.git
git remote add -f hoptoad git://github.com/thoughtbot/hoptoad_notifier.git
git remote add -f aasm git://github.com/rubyist/aasm.git
git remote add -f forgot git://github.com/greenisus/forgot_password.git
git remote add -f restful git://github.com/technoweenie/restful-authentication.git
(taken straight from evilchelu's example, but it should be the same
with random repositories).
Peeking at the transmission with Wireshark, there is a noticeable
pattern of 4-5s delays before _every_ "0008NAK\n" line sent by the
server.
Looking at upload-pack.c, it seems that the server does far too much
work when processing the "have" lines. I've only just read into this
area of code, but the rough idea seems to be:
[404: get_common_commits()]
for (H = every "have" line) {
[321: got_sha1()]
flag H and its parents (shallow!) as THEY_HAVE
[415: get_common_commits()]
if (we do not have H in our object store) {
[367: ok_to_give_up()]
for (W = every "want" object specified earlier) {
[338: reachable()]
walk the entire history to see if anything flagged
THEY_HAVE so far is reachable from W
}
[418: get_common_commits()]
if the innermost test succeeded for all W: ACK this H so the
client stops walking history from it
}
}
The entire loop seems to have O(h*w*n) (n=history) complexity, which
probably is to blame for the delays.
* Isn't this ok_to_give_up() test moot? If H is not in our object
store, it cannot be of any use in the transfer (of our history to
the client). So if we are going to fake an ACK to stop the client
digging on this side of his history, we might as well send it right
away. (And what does reaching a THEY_HAVE commit from all W's have
to do with it?)
* Even assuming it is not, it would save some work if the server
avoided walking the entire history for every H. For example, it
could buffer up all H's until a "0000\n" arrives, which currently
seems to be 32 haves, then check all of them in a single pass over
history. (Unfortunately the 'h' factor cannot be removed completely
unless we buffer all of them, which again defeats the point.)
Much of the code in question was added in 937a515 (upload-pack: stop
the other side when they have more roots than we do., 2006-07-05).
[I hope I'm making some sense, it's far too late here, but it was
either this or trying to understand it again in the morning.]
- Thomas
--
Thomas Rast
trast@student.ethz.ch
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH 6/6] git submodule add: Fix naming clash handling
From: Junio C Hamano @ 2008-09-13 2:24 UTC (permalink / raw)
To: Petr Baudis; +Cc: git, Mark Levedahl, Lars Hjemli
In-Reply-To: <20080912210924.31628.61593.stgit@localhost>
Petr Baudis <pasky@suse.cz> writes:
> This patch fixes git submodule add behaviour when we add submodule
> living at a same path as logical name of existing submodule. This
> can happen e.g. in case the user git mv's the previous submodule away
> and then git submodule add's another under the same name.
In short, name "example" was used to name the submodule bound at path
"init" in earlier tests, and the new one adds another submodule whose name
and path are both "example" and makes sure they do not get mixed up (and
the original code did mix them up).
> git-submodule.sh | 15 ++++++++++++---
> t/t7400-submodule-basic.sh | 11 +++++++++++
> 2 files changed, 23 insertions(+), 3 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index 1c39b59..3e4d839 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -201,10 +201,19 @@ cmd_add()
> git add "$path" ||
> die "Failed to add submodule '$path'"
>
> - git config -f .gitmodules submodule."$path".path "$path" &&
> - git config -f .gitmodules submodule."$path".url "$repo" &&
> + name="$path"
> + if git config -f .gitmodules submodule."$name".path; then
> + name="$path~"; i=1;
> + while git config -f .gitmodules submodule."$name".path; do
> + name="$path~$i"
> + i=$((i+1))
> + done
> + fi
> +
> + git config -f .gitmodules submodule."$name".path "$path" &&
> + git config -f .gitmodules submodule."$name".url "$repo" &&
> git add .gitmodules ||
> - die "Failed to register submodule '$path'"
> + die "Failed to register submodule '$path' (name '$name')"
> }
The logic of the fix seems to be correct, but shouldn't the test be like
this instead?
if git config -f .gitmodules "submodule.$name.path" >/dev/null
then
The same thing for "git config" used in the "while" loop.
Also I am not sure if name="$path~" is a good idea for two reasons:
- name suffixed with tilde and number looks too much like revision
expression.
- A, A~, A~1, A~2... looks ugly; A, A-0, A-1, A-2,... (or start counting
from 1 or 2) I would understand.
By the way, I noticed that cmd_add does not seem to cd_to_toplevel, and
accesses .gitmodules in the current working directory. Isn't this a bug?
How should "git submodule add" work from inside a subdirectory?
^ permalink raw reply
* git+ssh using 'plink' on windows
From: dhruva @ 2008-09-13 3:15 UTC (permalink / raw)
To: GIT SCM
Hello,
Since I use git on windows (without cygwin), I am keen to know if 'git+ssh' protocol work with Putty's plink? plink is a ssh like client on windows with almost similar features.
-dhruva
Unlimited freedom, unlimited storage. Get it now, on http://help.yahoo.com/l/in/yahoo/mail/yahoomail/tools/tools-08.html/
^ permalink raw reply
* Re: git+ssh using 'plink' on windows
From: dhruva @ 2008-09-13 3:18 UTC (permalink / raw)
To: GIT SCM
I was a bit impulsive in asking, I found an article which has some info that I am going to try:
http://my.afterdawn.com/agent_007/blog_entry.cfm/2909/git_and_cygwin
-dhruva
----- Original Message ----
> From: dhruva <dhruva@ymail.com>
> To: GIT SCM <git@vger.kernel.org>
> Sent: Saturday, 13 September, 2008 8:45:21 AM
> Subject: git+ssh using 'plink' on windows
>
> Hello,
> Since I use git on windows (without cygwin), I am keen to know if 'git+ssh'
> protocol work with Putty's plink? plink is a ssh like client on windows with
> almost similar features.
>
> -dhruva
>
>
>
> Unlimited freedom, unlimited storage.. Get it now, on
> http://help.yahoo.com/l/in/yahoo/mail/yahoomail/tools/tools-08.html/
Unlimited freedom, unlimited storage. Get it now, on http://help.yahoo.com/l/in/yahoo/mail/yahoomail/tools/tools-08.html/
^ permalink raw reply
* [RFC Redux] strbuf: Add method to convert byte-size to human readable form
From: Marcus Griep @ 2008-09-13 4:26 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Marcus Griep
Takes a strbuf as its first argument and appends the human-readable
form of 'value', the second argument, to that buffer.
e.g. strbuf_append_human_readable(sb, 1012, 0, 0, HR_SPACE)
produces "0.9 Ki".
Documented in strbuf.h; units can be directly appended to the strbuf
to produce "0.9 KiB/s", "0.9 KiB".
Supports SI magnitude prefixes as well as padding and spacing of
the units portion of the output.
Also, add in test cases to ensure it produces the expected output
and to demonstrate what different arguments do.
Signed-off-by: Marcus Griep <marcus@griep.us>
---
This is a redux of a prior patch as part of a series on count-objects
but is now split off and submitted on its own as an RFC for a library
function to be added to strbuf. If accepted, I'd like to standardize
upon this method for user visible byte-sizes, thoroughput, large object
counts, etc.
Provides similar functionality similar to the '-h' size output of du
in the default case.
Based on master, but also applies cleanly to next.
.gitignore | 1 +
Makefile | 2 +-
strbuf.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
strbuf.h | 30 +++++++++++++++
t/t0031-human-readable.sh | 49 ++++++++++++++++++++++++
test-human-read.c | 23 +++++++++++
6 files changed, 196 insertions(+), 1 deletions(-)
create mode 100755 t/t0031-human-readable.sh
create mode 100644 test-human-read.c
diff --git a/.gitignore b/.gitignore
index bbaf9de..251537b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -147,6 +147,7 @@ test-date
test-delta
test-dump-cache-tree
test-genrandom
+test-human-read
test-match-trees
test-parse-options
test-path-utils
diff --git a/Makefile b/Makefile
index 247cd2d..cd97468 100644
--- a/Makefile
+++ b/Makefile
@@ -1322,7 +1322,7 @@ endif
### Testing rules
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X test-human-read$X
all:: $(TEST_PROGRAMS)
diff --git a/strbuf.c b/strbuf.c
index 720737d..d9888fb 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -308,3 +308,95 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
return len;
}
+
+int strbuf_append_human_readable(struct strbuf *sb,
+ double val,
+ int maxlen, int scale,
+ int flags)
+{
+ const int maxscale = 7;
+
+ char *hr_prefixes[] = {
+ "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", NULL
+ };
+ char *hr_si_prefixes[] = {
+ "", "k", "M", "G", "T", "P", "E", "Z", "Y", NULL
+ };
+ char **prefix = &hr_prefixes[0];
+ int period = 1024;
+ int sign = val < 0 ? -1 : 1;
+ int retval = 0;
+
+ val *= sign;
+
+ if (flags & HR_PAD_UNIT) {
+ hr_prefixes[0] = " ";
+ hr_si_prefixes[0] = " ";
+ }
+
+ if (flags & HR_USE_SI) {
+ period = 1000;
+ prefix = &hr_si_prefixes[0];
+ }
+
+ if (scale == 0) {
+ if (maxlen == 0) {
+ scale = 1000;
+ maxlen = 3;
+ }
+ else {
+ int space = maxlen;
+ scale = 10;
+ while (--space > 0) {
+ scale *= 10;
+ }
+ }
+ }
+ else {
+ int space = 1;
+ int check = 10;
+ int setscale = scale;
+ while (check < scale) {
+ check *= 10;
+ ++space;
+ if (maxlen - space == 0)
+ setscale = check;
+ }
+ if (!maxlen)
+ maxlen = space;
+ scale = setscale;
+ }
+
+ while (val >= scale && *prefix++)
+ val /= period;
+
+ if (val >= scale) {
+ int needed = 0;
+ while (val >= scale) {
+ val /= period;
+ --needed;
+ }
+ if (needed < retval)
+ retval = needed;
+ }
+
+ strbuf_addf(sb, "%f", sign * val);
+
+ if (maxlen) {
+ int signlen = sign == -1 ? 1 : 0;
+ maxlen -= (sb->buf[maxlen-1+signlen] == '.' ? 1 : 0);
+ if (maxlen <= 0) {
+ strbuf_setlen(sb, 0);
+ retval = maxlen - 1;
+ } else {
+ strbuf_setlen(sb, maxlen + signlen);
+ }
+ }
+
+ strbuf_addf(sb, "%s%s",
+ flags & HR_SPACE ? " " : "",
+ *prefix
+ );
+
+ return retval;
+}
diff --git a/strbuf.h b/strbuf.h
index eba7ba4..305ef55 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -125,4 +125,34 @@ extern int strbuf_getline(struct strbuf *, FILE *, int);
extern void stripspace(struct strbuf *buf, int skip_comments);
extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
+/*
+ * strbuf_append_human_readable
+ *
+ * 'val': value to be metrically-reduced to a human-readable number
+ * 'maxlen': maximum number of characters to be taken up by the reduced 'val'
+ * not including the sign or magnitude (i.e. 'Ki') characters;
+ * when 'maxlen' is 0 length is controled by 'scale'
+ * 'scale': when 'val' is greater than 'scale', 'val' is reduced by the
+ * period (default 1024, see 'flags') until it is less than 'scale';
+ * when 'scale' is 0, 'val' is reduced until it fits in 'maxlen';
+ * when 'scale' and 'maxlen' are both zero, 'scale' defaults to 1000
+ * 'flags': HR_USE_SI: uses a period of 1000 and uses SI magnitude prefixes
+ * HR_SPACE: inserts a space between the reduced 'val' and the units
+ * HR_PAD_UNIT: instead of an empty string for singles, pads with
+ * spaces to the length of the magnitude prefixes
+ *
+ * Returns 0 if 'val' is successfully reduced and fits in 'maxlen', otherwise
+ * returns -n where n is the number of additional characters necessary to
+ * fully fit the reduced value.
+ */
+
+#define HR_USE_SI 0x01
+#define HR_SPACE 0x02
+#define HR_PAD_UNIT 0x04
+
+extern int strbuf_append_human_readable(struct strbuf *,
+ double val,
+ int maxlen, int scale,
+ int flags);
+
#endif /* STRBUF_H */
diff --git a/t/t0031-human-readable.sh b/t/t0031-human-readable.sh
new file mode 100755
index 0000000..d4266f2
--- /dev/null
+++ b/t/t0031-human-readable.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description="Test human-readable formatting"
+
+. ./test-lib.sh
+
+HR_NONE=0
+HR_USE_SI=1
+HR_SPACE=2
+HR_PAD_UNIT=4
+
+test_hr () {
+ test_expect_success "'$5' ($6)" "
+ test-human-read $1 $2 $3 $4 $5
+ [[ $? -eq $6 ]]
+ "
+}
+
+test_hr 1012 0 0 $HR_SPACE "0.9 Ki" 0
+test_hr 1012 0 0 $(($HR_SPACE+$HR_USE_SI)) "1.0 k" 0
+test_hr -1012 0 0 $(($HR_SPACE+$HR_USE_SI)) "-1.0 k" 0
+test_hr 1012 5 0 $(($HR_SPACE+$HR_PAD_UNIT)) "1012 " 0
+test_hr 1012 5 0 $HR_SPACE "1012 " 0
+test_hr 1012 5 0 $(($HR_USE_SI+$HR_SPACE+$HR_PAD_UNIT)) "1012 " 0
+test_hr 1012 5 0 $(($HR_USE_SI+$HR_SPACE)) "1012 " 0
+test_hr 1012 4 0 $HR_NONE "1012" 0
+test_hr 1012 3 0 $HR_NONE "0.9Ki" 0
+test_hr 1012 2 0 $HR_NONE "0Ki" 0
+test_hr 1012 1 0 $HR_NONE "0Ki" 0
+test_hr 1012 0 0 $HR_NONE "0.9Ki" 0
+test_hr -1012 3 0 $HR_NONE "-0.9Ki" 0
+test_hr -1012 2 0 $HR_NONE "-0Ki" 0
+test_hr -1012 1 0 $HR_NONE "-0Ki" 0
+test_hr -1012 0 0 $HR_NONE "-0.9Ki" 0
+test_hr 2024 4 0 $HR_NONE "2024" 0
+test_hr 20240 4 0 $HR_NONE "19.7Ki" 0
+test_hr 1012 0 1000 $HR_NONE "0.9Ki" 0
+test_hr $((506*1024*1024)) 0 1000000 $HR_NONE "518144Ki" 0
+test_hr $((506*1024*1024)) 7 1000000 $HR_NONE "518144Ki" 0
+test_hr $((506*1024*1024)) 6 1000000 $HR_NONE "518144Ki" 0
+test_hr $((506*1024*1024)) 5 1000000 $HR_NONE "506.0Mi" 0
+test_hr $((506*1024*1024)) 4 1000000 $HR_NONE "506Mi" 0
+test_hr $((506*1024*1024)) 3 1000000 $HR_NONE "506Mi" 0
+test_hr $((506*1024*1024)) 2 1000000 $HR_NONE "0Gi" 0
+test_hr $((506*1024*1024*1024)) 0 1000000 $HR_NONE "518144Mi" 0
+test_hr $((506*1024*1024*1024)) 0 1000000 $HR_USE_SI "543313Mi" 0
+test_hr 0 0 0 $HR_NONE "0" 0
+
+test_done
diff --git a/test-human-read.c b/test-human-read.c
new file mode 100644
index 0000000..7890922
--- /dev/null
+++ b/test-human-read.c
@@ -0,0 +1,23 @@
+#include "builtin.h"
+#include "strbuf.h"
+
+int main(int argc, char **argv) {
+ if (argc != 6) {
+ exit(-1);
+ }
+
+ struct strbuf sb;
+ strbuf_init(&sb, 0);
+
+ int retval = strbuf_append_human_readable(&sb,
+ atof(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
+
+ int failed = strcmp(sb.buf, argv[5]);
+
+ fprintf( stderr, failed ? "Failure" : "Success" );
+ fprintf( stderr, ": Act '%s'; Exp '%s'\n", sb.buf, argv[5] );
+ fprintf( stderr, "Return Value: %d\n", retval );
+
+ if(failed) return -1;
+ return retval;
+}
--
1.6.0.1.451.gc8d31
^ permalink raw reply related
* Re: [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase
From: Junio C Hamano @ 2008-09-13 5:08 UTC (permalink / raw)
To: Thomas Rast; +Cc: git
In-Reply-To: <1221147525-5589-2-git-send-email-trast@student.ethz.ch>
Thomas Rast <trast@student.ethz.ch> writes:
> +RECOVERING FROM UPSTREAM REBASE
> +-------------------------------
> +
> +This section briefly explains the problems that arise from rebasing or
> +rewriting published branches, and shows how to recover.
The largest issue of "The problem" is that the person who rebases causes
this problem to others, _forcing_ his downstream to recover. This intro
needs to make it clear the distinction between the person who rebases, who
suffers is forced to recover as the consequence.
> + o---o---o---o---o master
> + \
> + o---o---o---o---o subsystem
> + \
> + *---*---* topic
>...
> +If 'subsystem' is rebased against master, the following happens:
>...
> + o---o---o---o---o master
> + | \
> + | o'--o'--o'--o'--o' subsystem
> + \
> + o---o---o---o---o---*---*---* topic
Make the original upstream a bit longer in the "after" picture, explaining
that "your upstream subsystem rebased on top of its own upstream after it
gets updated", so that the part that are unchanged in two pictures are not
drawn differently like you did above.
In other words, draw it like this. It is much easier to see what's
changed and what's unchanged, if the part that hasn't changed stayed
unchanged in the picture:
o---o---o---o---o master
\
o---o---o---o---o subsystem
\
*---*---* topic
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic
> +Note that while we have marked your own commits with a '*', there is
> +nothing that distinguishes them from the commits that previously were
> +on 'subsystem'. Luckily, 'git-rebase' knows to skip commits that are
> +textually the same as commits in the upstream. So if you say
> +(assuming you're on 'topic')
There is no luck involved in "git rebase" knowing how to do this -- this
is by design.
But more importantly, at this point, there is a break in the flow of
thought in this section. Step back and read what you wrote, pretending as
if you are reading the section for the first time, and notice:
* The readers were shown how the topology before and after the
subsystem's rebase looked like;
* The readers haven't been told what you are trying teach them now. Yes,
I know that you are going to tell them how to transplant their own
commits on top of updated subsystem, but they don't know that yet;
* Some of the readers may not even understand why it is a bad idea to
keep building on top of the old subsystem without rebasing on top of
the rebased subsystem at this point.
Only when the readers know that the objective is to transplant these three
top commits, they would start appreciating the difficulty (i.e. you cannot
tell the commits apart by looking at the topology alone) of rebase the
reader has to do, and the smart (i.e. if you are lucky, the rebase your
upstream did may have been a simple one) git-rebase uses to help them.
It would suffice to insert something like this before "Note that...".
To continue working from here, you need to transplant your own
commits (marked as '*') on top of the "subsystem", which is now
rebased.
But see footnote below.
> +This becomes a ripple effect to anyone downstream of the first rebase:
> +anyone downstream from 'topic' now needs to rebase too, and so on.
This calls for a stronger wording than "needs to", perhaps "forced to".
> +Things get more complicated if your upstream used `git rebase
> +--interactive` (or `commit --amend` or `reset --hard HEAD^`).
I do not think this section is absolutely necessary. The upstream may
have done a simple rebase, which may have conflicted with the changes in
its own upstream.
> +To fix this, you have to manually transplant your own part of the
> +history to the new branch head. Looking at `git log`, you should be
> +able to determine that three commits on 'topic' are yours. Again
> +assuming you are already on 'topic', you can do
> +------------
> + git rebase --onto subsystem HEAD~3
> +------------
> +to put things right.
HEAD~3 would _work_, but it often is easier to visualize this (perhaps in
your head, or in "gitk HEAD origin origin@{1}"):
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic
and say:
$ git rebase --onto subsystem subsystem@{1}
The reflog reference "1" may be larger depending on the number of times
you fetched from them without rebasing, though.
[Footnote]
You did not cover why midstream rebase _forces_ downstream to rebase. If
the leaf-level person did not know better, or did not care, starting from
this topology:
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic
the leaf person can keep building on top of the old topic, and later when
the topic is mature, have subsystem merge the result. If the rebase the
subsystem did was simple enough, the merge will be easy to resolve (both
sides modifying the same way).
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
\ /
*---*---*---*---*---*---*
The problem is that the resulting history will keep two copies of the
morally equivalent commits from the subsystem. You know that, and I know
that, but the purpose of the document is to explain it to people who do
not know it yet.
^ permalink raw reply
* [ANNOUNCE] GIT 1.6.0.2
From: Junio C Hamano @ 2008-09-13 6:13 UTC (permalink / raw)
To: git; +Cc: linux-kernel
The latest maintenance release GIT 1.6.0.2 is available at the
usual places:
http://www.kernel.org/pub/software/scm/git/
git-1.6.0.2.tar.{gz,bz2} (source tarball)
git-htmldocs-1.6.0.2.tar.{gz,bz2} (preformatted docs)
git-manpages-1.6.0.2.tar.{gz,bz2} (preformatted docs)
The RPM binary packages for a few architectures are also provided in:
RPMS/$arch/git-*-1.6.0.2-1.fc9.$arch.rpm (RPM)
----------------------------------------------------------------
GIT v1.6.0.2 Release Notes
==========================
Fixes since v1.6.0.1
--------------------
* Installation on platforms that needs .exe suffix to git-* programs were
broken in 1.6.0.1.
* Installation on filesystems without symbolic links support did not
work well.
* In-tree documentations and test scripts now use "git foo" form to set a
better example, instead of the "git-foo" form (which is an acceptable
form if you have "PATH=$(git --exec-path):$PATH" in your script)
* Many commands did not use the correct working tree location when used
with GIT_WORK_TREE environment settings.
* Some systems needs to use compatibility fnmach and regex libraries
independent from each other; the compat/ area has been reorganized to
allow this.
* "git apply --unidiff-zero" incorrectly applied a -U0 patch that inserts
a new line before the second line.
* "git blame -c" did not exactly work like "git annotate" when range
boundaries are involved.
* "git checkout file" when file is still unmerged checked out contents from
a random high order stage, which was confusing.
* "git clone $there $here/" with extra trailing slashes after explicit
local directory name $here did not work as expected.
* "git diff" on tracked contents with CRLF line endings did not drive "less"
intelligently when showing added or removed lines.
* "git diff --dirstat -M" did not add changes in subdirectories up
correctly for renamed paths.
* "git diff --cumulative" did not imply "--dirstat".
* "git for-each-ref refs/heads/" did not work as expected.
* "git gui" allowed users to feed patch without any context to be applied.
* "git gui" botched parsing "diff" output when a line that begins with two
dashes and a space gets removed or a line that begins with two pluses
and a space gets added.
* "git gui" translation updates and i18n fixes.
* "git index-pack" is more careful against disk corruption while completing
a thin pack.
* "git log -i --grep=pattern" did not ignore case; neither "git log -E
--grep=pattern" triggered extended regexp.
* "git log --pretty="%ad" --date=short" did not use short format when
showing the timestamp.
* "git log --author=author" match incorrectly matched with the
timestamp part of "author " line in commit objects.
* "git log -F --author=author" did not work at all.
* Build procedure for "git shell" that used stub versions of some
functions and globals was not understood by linkers on some platforms.
* "git stash" was fooled by a stat-dirty but otherwise unmodified paths
and refused to work until the user refreshed the index.
* "git svn" was broken on Perl before 5.8 with recent fixes to reduce
use of temporary files.
* "git verify-pack -v" did not work correctly when given more than one
packfile.
Also contains many documentation updates.
----------------------------------------------------------------
Changes since v1.6.0.1 are as follows:
Alex Riesen (1):
Fix use of hardlinks in "make install"
Alexander Gavrilov (1):
git-gui: Fix string escaping in po2msg.sh
Alexandre Bourget (2):
git-gui: Update french translation
git-gui: update all remaining translations to French.
Andreas Färber (1):
Makefile: always provide a fallback when hardlinks fail
Arjen Laarhoven (1):
Use compatibility regex library for OSX/Darwin
Ask Bjørn Hansen (1):
Document sendemail.envelopesender configuration
Björn Steinbrink (1):
for-each-ref: Allow a trailing slash in the patterns
Clemens Buchacher (2):
git gui: show diffs with a minimum of 1 context line
clone: fix creation of explicitly named target directory
Gustaf Hendeby (1):
Document clarification: gitmodules, gitattributes
Heikki Orsila (3):
Start conforming code to "git subcmd" style
Improve documentation for --dirstat diff option
Start conforming code to "git subcmd" style part 2
Jeff King (4):
Fix "git log -i --grep"
pretty=format: respect date format options
checkout: fix message when leaving detached HEAD
Use compatibility regex library also on FreeBSD
Johan Herland (1):
Bring local clone's origin URL in line with that of a remote clone
Johannes Sixt (1):
Use compatibility regex library also on AIX
Jonas Fonseca (1):
Fix passwd(5) ref and reflect that commit doens't use commit-tree
Junio C Hamano (17):
ctype.c: protect tiny C preprocessor constants
shell: do not play duplicated definition games to shrink the executable
Fix example in git-name-rev documentation
git-apply: Loosen "match_beginning" logic
checkout: do not check out unmerged higher stages randomly
gitattributes: -crlf is not binary
diff: Help "less" hide ^M from the output
'git foo' program identifies itself without dash in die() messages
Start 1.6.0.2 maintenance cycle
diff --cumulative is a sub-option of --dirstat
log --author/--committer: really match only with name part
"blame -c" should be compatible with "annotate"
Mention the fact that 'git annotate' is only for backward compatibility.
stash: refresh the index before deciding if the work tree is dirty
Update draft release notes for 1.6.0.2
Update draft release notes for 1.6.0.2
GIT 1.6.0.2
Linus Torvalds (2):
index-pack: be careful after fixing up the header/footer
Fix '--dirstat' with cross-directory renaming
Marcus Griep (2):
Git.pm: Use File::Temp->tempfile instead of ->new
git-svn: Fixes my() parameter list syntax error in pre-5.8 Perl
Miklos Vajna (2):
Makefile: add merge_recursive.h to LIB_H
t7501: always use test_cmp instead of diff
Nanako Shiraishi (4):
tests: use "git xyzzy" form (t0000 - t3599)
tests: use "git xyzzy" form (t3600 - t6999)
tests: use "git xyzzy" form (t7000 - t7199)
tests: use "git xyzzy" form (t7200 - t9001)
Nguyễn Thái Ngọc Duy (6):
index-pack: setup git repository
diff*: fix worktree setup
grep: fix worktree setup
read-tree: setup worktree if merge is required
update-index: fix worktree setup
setup_git_directory(): fix move to worktree toplevel directory
Nicolas Pitre (7):
discard revindex data when pack list changes
pack-objects: improve returned information from write_one()
improve reliability of fixup_pack_header_footer()
pack-objects: use fixup_pack_header_footer()'s validation mode
index-pack: use fixup_pack_header_footer()'s validation mode
fixup_pack_header_footer(): use nicely aligned buffer sizes
improve handling of sideband message display
Paolo Bonzini (1):
make git-shell paranoid about closed stdin/stdout/stderr
Paolo Ciarrocchi (1):
tutorial: gentler illustration of Alice/Bob workflow using gitk
Petr Baudis (1):
bash completion: Hide more plumbing commands
Ralf Wildenhues (1):
Fix some manual typos.
Ramsay Allan Jones (2):
Fix a warning (on cygwin) to allow -Werror
Suppress some bash redirection error messages
SZEDER Gábor (3):
Documentation: fix reference to a for-each-ref option
Documentation: fix disappeared lines in 'git stash' manpage
Documentation: minor cleanup in a use case in 'git stash' manual
Shawn O. Pearce (2):
pack-objects: Allow missing base objects when creating thin packs
git-gui: Fix diff parsing for lines starting with "--" or "++"
Teemu Likonen (1):
config.txt: Add missing colons after option name
Yann Dirson (1):
Document gitk --argscmd flag.
^ permalink raw reply
* [PATCH] git-gui: Updated German translation.
From: Christian Stimming @ 2008-09-13 8:25 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
[-- Attachment #1: Type: text/plain, Size: 120 bytes --]
Patch against today's master of git-gui.git at repo.or.cz. Attached to avoid
whitespace problems.
Regards,
Christian
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-git-gui-Updated-German-translation.patch --]
[-- Type: text/x-diff; charset="us-ascii"; name="0001-git-gui-Updated-German-translation.patch", Size: 7970 bytes --]
From 75a98bb3189683dfedb3a2bccdec0227a57ea6d6 Mon Sep 17 00:00:00 2001
From: Christian Stimming <stimming@tuhh.de>
Date: Sat, 13 Sep 2008 10:24:47 +0200
Subject: [PATCH] git-gui: Updated German translation.
---
po/de.po | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 172 insertions(+), 21 deletions(-)
diff --git a/po/de.po b/po/de.po
index fa43947..793cca1 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-02 08:58+0200\n"
-"PO-Revision-Date: 2008-08-02 09:09+0200\n"
+"POT-Creation-Date: 2008-09-13 10:20+0200\n"
+"PO-Revision-Date: 2008-09-13 10:24+0200\n"
"Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
@@ -110,7 +110,15 @@ msgstr "Teilweise bereitgestellt zum Eintragen"
msgid "Staged for commit, missing"
msgstr "Bereitgestellt zum Eintragen, fehlend"
-#: git-gui.sh:1597
+#: git-gui.sh:1658
+msgid "File type changed, not staged"
+msgstr "Dateityp geändert, nicht bereitgestellt"
+
+#: git-gui.sh:1659
+msgid "File type changed, staged"
+msgstr "Dateityp geändert, bereitgestellt"
+
+#: git-gui.sh:1661
msgid "Untracked, not staged"
msgstr "Nicht unter Versionskontrolle, nicht bereitgestellt"
@@ -396,15 +404,7 @@ msgstr "Alle kopieren"
msgid "File:"
msgstr "Datei:"
-#: git-gui.sh:2589
-msgid "Apply/Reverse Hunk"
-msgstr "Kontext anwenden/umkehren"
-
-#: git-gui.sh:2696
-msgid "Apply/Reverse Line"
-msgstr "Zeile anwenden/umkehren"
-
-#: git-gui.sh:2711
+#: git-gui.sh:2834
msgid "Refresh"
msgstr "Aktualisieren"
@@ -416,7 +416,35 @@ msgstr "Schriftgröße verkleinern"
msgid "Increase Font Size"
msgstr "Schriftgröße vergrößern"
-#: git-gui.sh:2646
+#: git-gui.sh:2870
+msgid "Apply/Reverse Hunk"
+msgstr "Kontext anwenden/umkehren"
+
+#: git-gui.sh:2875
+msgid "Apply/Reverse Line"
+msgstr "Zeile anwenden/umkehren"
+
+#: git-gui.sh:2885
+msgid "Run Merge Tool"
+msgstr "Zusammenführungswerkzeug"
+
+#: git-gui.sh:2890
+msgid "Use Remote Version"
+msgstr "Entfernte Version benutzen"
+
+#: git-gui.sh:2894
+msgid "Use Local Version"
+msgstr "Lokale Version benutzen"
+
+#: git-gui.sh:2898
+msgid "Revert To Base"
+msgstr "Ursprüngliche Version benutzen"
+
+#: git-gui.sh:2906
+msgid "Stage Working Copy"
+msgstr "Arbeitskopie bereitstellen"
+
+#: git-gui.sh:2925
msgid "Unstage Hunk From Commit"
msgstr "Kontext aus Bereitstellung herausnehmen"
@@ -498,7 +526,15 @@ msgstr "Version kopieren"
msgid "Do Full Copy Detection"
msgstr "Volle Kopie-Erkennung"
-#: lib/blame.tcl:388
+#: lib/blame.tcl:263
+msgid "Show History Context"
+msgstr "Historien-Kontext anzeigen"
+
+#: lib/blame.tcl:266
+msgid "Blame Parent Commit"
+msgstr "Elternversion annotieren"
+
+#: lib/blame.tcl:394
#, tcl-format
msgid "Reading %s..."
msgstr "%s lesen..."
@@ -547,7 +583,19 @@ msgstr "Eintragender:"
msgid "Original File:"
msgstr "Ursprüngliche Datei:"
-#: lib/blame.tcl:925
+#: lib/blame.tcl:990
+msgid "Cannot find parent commit:"
+msgstr "Elternversion kann nicht gefunden werden:"
+
+#: lib/blame.tcl:1001
+msgid "Unable to display parent"
+msgstr "Elternversion kann nicht angezeigt werden"
+
+#: lib/blame.tcl:1002 lib/diff.tcl:191
+msgid "Error loading diff:"
+msgstr "Fehler beim Laden des Vergleichs:"
+
+#: lib/blame.tcl:1142
msgid "Originally By:"
msgstr "Ursprünglich von:"
@@ -1494,11 +1542,7 @@ msgstr "Git-Projektarchiv (Unterprojekt)"
msgid "* Binary file (not showing content)."
msgstr "* Binärdatei (Inhalt wird nicht angezeigt)"
-#: lib/diff.tcl:185
-msgid "Error loading diff:"
-msgstr "Fehler beim Laden des Vergleichs:"
-
-#: lib/diff.tcl:303
+#: lib/diff.tcl:313
msgid "Failed to unstage selected hunk."
msgstr ""
"Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung."
@@ -1586,6 +1630,15 @@ msgstr ""
msgid "Do Nothing"
msgstr "Nichts tun"
+#: lib/index.tcl:419
+msgid "Reverting selected files"
+msgstr "Änderungen in gewählten Dateien verwerfen"
+
+#: lib/index.tcl:423
+#, tcl-format
+msgid "Reverting %s"
+msgstr "Änderungen in %s verwerfen"
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1730,6 +1783,96 @@ msgstr "Abbruch fehlgeschlagen."
msgid "Abort completed. Ready."
msgstr "Abbruch durchgeführt. Bereit."
+#: lib/mergetool.tcl:14
+msgid "Force resolution to the base version?"
+msgstr "Konflikt durch Basisversion ersetzen?"
+
+#: lib/mergetool.tcl:15
+msgid "Force resolution to this branch?"
+msgstr "Konflikt durch diesen Zweig ersetzen?"
+
+#: lib/mergetool.tcl:16
+msgid "Force resolution to the other branch?"
+msgstr "Konflikt durch anderen Zweig ersetzen?"
+
+#: lib/mergetool.tcl:20
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"Hinweis: Der Vergleich zeigt nur konfliktverursachende Änderungen an.\n"
+"\n"
+"»%s« wird überschrieben.\n"
+"\n"
+"Diese Operation kann nur rückgängig gemacht werden, wenn die\n"
+"Zusammenführung erneut gestartet wird."
+
+#: lib/mergetool.tcl:32
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "Auflösung hinzugefügt für %s"
+
+#: lib/mergetool.tcl:119
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr ""
+"Konflikte durch gelöschte Dateien oder symbolische Links können nicht durch "
+"das Zusamenführungswerkzeug gelöst werden."
+
+#: lib/mergetool.tcl:124
+msgid "Conflict file does not exist"
+msgstr "Konflikt-Datei existiert nicht"
+
+#: lib/mergetool.tcl:236
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "Kein GUI Zusammenführungswerkzeug: »%s«"
+
+#: lib/mergetool.tcl:240
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "Unbekanntes Zusammenführungswerkzeug: »%s«"
+
+#: lib/mergetool.tcl:275
+msgid "Merge tool is already running, terminate it?"
+msgstr "Zusammenführungswerkzeug läuft bereits. Soll es abgebrochen werden?"
+
+#: lib/mergetool.tcl:295
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Fehler beim Abrufen der Dateiversionen:\n"
+"%s"
+
+#: lib/mergetool.tcl:315
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"Zusammenführungswerkzeug konnte nicht gestartet werden:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:319
+msgid "Running merge tool..."
+msgstr "Zusammenführungswerkzeug starten..."
+
+#: lib/mergetool.tcl:347 lib/mergetool.tcl:363
+msgid "Merge tool failed."
+msgstr "Zusammenführungswerkzeug fehlgeschlagen."
+
+#: lib/mergetool.tcl:353
+#, tcl-format
+msgid "File %s unchanged, still accept as resolved?"
+msgstr "Datei »%s« unverändert. Trotzdem Konflikt als gelöst akzeptieren?"
+
#: lib/option.tcl:95
msgid "Restore Defaults"
msgstr "Voreinstellungen wiederherstellen"
@@ -1767,7 +1910,11 @@ msgstr "Ausführlichkeit der Zusammenführen-Meldungen"
msgid "Show Diffstat After Merge"
msgstr "Vergleichsstatistik nach Zusammenführen anzeigen"
-#: lib/option.tcl:123
+#: lib/option.tcl:122
+msgid "Use Merge Tool"
+msgstr "Zusammenführungswerkzeug"
+
+#: lib/option.tcl:124
msgid "Trust File Modification Timestamps"
msgstr "Auf Dateiänderungsdatum verlassen"
@@ -1788,6 +1935,10 @@ msgid "Minimum Letters To Blame Copy On"
msgstr "Mindestzahl Zeichen für Kopie-Annotieren"
#: lib/option.tcl:128
+msgid "Blame History Context Radius (days)"
+msgstr "Anzahl Tage für Historien-Kontext"
+
+#: lib/option.tcl:129
msgid "Number of Diff Context Lines"
msgstr "Anzahl der Kontextzeilen beim Vergleich"
--
1.6.0.rc1.34.g0fe8c
^ permalink raw reply related
* Re: [ANNOUNCE] GIT 1.6.0-rc2
From: David Miller @ 2008-09-13 8:33 UTC (permalink / raw)
To: gitster; +Cc: peterz, git, linux-kernel
In-Reply-To: <20080807.052648.239243998.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Thu, 07 Aug 2008 05:26:48 -0700 (PDT)
> From: Junio C Hamano <gitster@pobox.com>
> Date: Thu, 07 Aug 2008 03:00:25 -0700
>
> > Peter Zijlstra <peterz@infradead.org> writes:
> >
> > > Quick question - where does one go to find out the cool new features
> > > that make it 1.6 and should convince me to upgrade and try this whicked
> > > new release?
> >
> > Draft release notes for 1.6.0 was posted to the list some time ago
> > already, but as always:
> >
> > http://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.6.0.txt
>
> Just FYI, I have some issue with 1.6.x git when pulling remotely from
> it on sparc64. I suspect it is the usual unaligned access issue and I
> will debug it further soon.
As a followup this turned out to be the classic "PATH when doing GIT over
SSH" problem.
I have to say this is very unfun to debug, and even less fun to "fix"
even once you know this is the problem. And what's more I know this is
the second time I've had to spend a night debugging this very problem.
I ended up having to make a ~/.ssh/environment file and then restart my
SSH server with "PermitUserEnvironment yes" added to sshd_config.
But I can't believe this is what I have to do just to pull from a machine
where I have GIT only installed in my home directory. What if I were just
a normal user and couldn't change the SSHD config? What hoops would I
need to jump through to get my PATH setup correctly? :)
It doesn't even work to put ~/bin into the PATH listed in the system wide
/etc/environment, because that does not do tilde expansion, SSHD just takes
it as-is.
Wouldn't it make sense to put the bindir into PATH when we try to do
execv_git_cmd()? The code has already put the gitexecdir into the
PATH at this point.
Thanks!
^ permalink raw reply
* Re: [ANN] mtn2git v0.1
From: Jakub Narebski @ 2008-09-13 9:45 UTC (permalink / raw)
To: Felipe Contreras; +Cc: devel, openembedded-devel, monotone-devel, git
In-Reply-To: <94a0d4530809121559w5f644174j461ec61cb2327fd8@mail.gmail.com>
"Felipe Contreras" <felipe.contreras@gmail.com> writes:
> This is the result of various experiments I've been doing while trying
> to import mtn repositories into git. I've looked into other mtn2git
> scripts but none fitted my needs.
mtn or mnt?
> After some RFCs on git and monotone mailing lists it seems now that
> the script is going in the right direction.
When you feel this script to be ready, could you add it to the
"Interaction with other Revision Control Systems" section on
http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
As far as I can see there ain't any Monotone to Git converter on this
list.
TIA
--
Jakub Narebski
Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [ANN] mtn2git v0.1
From: Felipe Contreras @ 2008-09-13 10:52 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git, monotone-devel, devel, openembedded-devel
In-Reply-To: <m3d4j8nzy9.fsf@localhost.localdomain>
On Sat, Sep 13, 2008 at 12:45 PM, Jakub Narebski <jnareb@gmail.com> wrote:
> "Felipe Contreras" <felipe.contreras@gmail.com> writes:
>
>> This is the result of various experiments I've been doing while trying
>> to import mtn repositories into git. I've looked into other mtn2git
>> scripts but none fitted my needs.
>
> mtn or mnt?
monotone = mtn
>> After some RFCs on git and monotone mailing lists it seems now that
>> the script is going in the right direction.
>
> When you feel this script to be ready, could you add it to the
> "Interaction with other Revision Control Systems" section on
> http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
> As far as I can see there ain't any Monotone to Git converter on this
> list.
Ok, done. I think it's ready if you can bare the slowness of the
'checkout' method. The only missing feature is tags, but should be
easy to implement.
--
Felipe Contreras
^ permalink raw reply
* Re: [PATCH 6/6] git submodule add: Fix naming clash handling
From: Lars Hjemli @ 2008-09-13 11:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Petr Baudis, git, Mark Levedahl
In-Reply-To: <7v63p0n5pv.fsf@gitster.siamese.dyndns.org>
On Sat, Sep 13, 2008 at 4:24 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Petr Baudis <pasky@suse.cz> writes:
>
>> This patch fixes git submodule add behaviour when we add submodule
>> living at a same path as logical name of existing submodule. This
>> can happen e.g. in case the user git mv's the previous submodule away
>> and then git submodule add's another under the same name.
>
> In short, name "example" was used to name the submodule bound at path
> "init" in earlier tests, and the new one adds another submodule whose name
> and path are both "example" and makes sure they do not get mixed up (and
> the original code did mix them up).
>
>> git-submodule.sh | 15 ++++++++++++---
>> t/t7400-submodule-basic.sh | 11 +++++++++++
>> 2 files changed, 23 insertions(+), 3 deletions(-)
>>
>> diff --git a/git-submodule.sh b/git-submodule.sh
>> index 1c39b59..3e4d839 100755
>> --- a/git-submodule.sh
>> +++ b/git-submodule.sh
>> @@ -201,10 +201,19 @@ cmd_add()
>> git add "$path" ||
>> die "Failed to add submodule '$path'"
>>
>> - git config -f .gitmodules submodule."$path".path "$path" &&
>> - git config -f .gitmodules submodule."$path".url "$repo" &&
>> + name="$path"
>> + if git config -f .gitmodules submodule."$name".path; then
>> + name="$path~"; i=1;
>> + while git config -f .gitmodules submodule."$name".path; do
>> + name="$path~$i"
>> + i=$((i+1))
>> + done
>> + fi
>> +
>> + git config -f .gitmodules submodule."$name".path "$path" &&
>> + git config -f .gitmodules submodule."$name".url "$repo" &&
>> git add .gitmodules ||
>> - die "Failed to register submodule '$path'"
>> + die "Failed to register submodule '$path' (name '$name')"
>> }
>
> The logic of the fix seems to be correct, but shouldn't the test be like
> this instead?
>
> if git config -f .gitmodules "submodule.$name.path" >/dev/null
> then
>
> The same thing for "git config" used in the "while" loop.
Yeah, redirecting to /dev/null seems like a good idea.
> Also I am not sure if name="$path~" is a good idea for two reasons:
>
> - name suffixed with tilde and number looks too much like revision
> expression.
>
> - A, A~, A~1, A~2... looks ugly; A, A-0, A-1, A-2,... (or start counting
> from 1 or 2) I would understand.
I'd just exit with an informative error if submodule.$name already
exists in .git/config.
> By the way, I noticed that cmd_add does not seem to cd_to_toplevel, and
> accesses .gitmodules in the current working directory. Isn't this a bug?
Not really, since `git submodule` must be executed from the toplevel
($SUBDIRECTORY_OK is undefined, so the cd_to_toplevel in cmd_sync and
cmd_summary seems to be noops).
--
larsh
^ permalink raw reply
* Re: [ANN] mtn2git v0.1
From: Jakub Narebski @ 2008-09-13 12:02 UTC (permalink / raw)
To: Felipe Contreras; +Cc: git, monotone-devel, devel, openembedded-devel
In-Reply-To: <94a0d4530809130352v5775be53sc14b354b8c1dae15@mail.gmail.com>
On Sat, 13 Sep 2008, Felipe Contreras wrote:
> On Sat, Sep 13, 2008 at 12:45 PM, Jakub Narebski <jnareb@gmail.com> wrote:
>> "Felipe Contreras" <felipe.contreras@gmail.com> writes:
>>
>>> This is the result of various experiments I've been doing while trying
>>> to import mtn repositories into git. I've looked into other mtn2git
>>> scripts but none fitted my needs.
>>
>> mtn or mnt?
>
> monotone = mtn
Thanks.
My confusion resulted from the fact that 'monotone' has 'n' both
before and after 't'.
>>> After some RFCs on git and monotone mailing lists it seems now that
>>> the script is going in the right direction.
>>
>> When you feel this script to be ready, could you add it to the
>> "Interaction with other Revision Control Systems" section on
>> http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
>> As far as I can see there ain't any Monotone to Git converter on this
>> list.
>
> Ok, done. I think it's ready if you can bare the slowness of the
> 'checkout' method. The only missing feature is tags, but should be
> easy to implement.
Thank you.
BTW. did you have any problems with (from what I understand) slightly
different concept of branches between Monotone and Git?
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: O(#haves*...) behaviour in "have <sha>" processing in upload-pack
From: Thomas Rast @ 2008-09-13 12:18 UTC (permalink / raw)
To: git
In-Reply-To: <200809130211.14091.trast@student.ethz.ch>
[-- Attachment #1: Type: text/plain, Size: 811 bytes --]
I wrote:
> * Isn't this ok_to_give_up() test moot? If H is not in our object
> store, it cannot be of any use in the transfer (of our history to
> the client). So if we are going to fake an ACK to stop the client
> digging on this side of his history, we might as well send it right
> away.
Never mind this part, it's wrong:
Let B=$(merge-base H W). Suppose H is unknown to the server, but B is
known. Then sending a fake ACK as a reply to H will cause
* the client to believe we have everything reachable from H, including
B, and cease sending any history reachable from H; and thus
* the server to believe that the client does not have B, since it did
not list this commit in a "have" line.
Sorry for the noise.
- Thomas
--
Thomas Rast
trast@student.ethz.ch
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [ANN] mtn2git v0.1
From: Felipe Contreras @ 2008-09-13 15:21 UTC (permalink / raw)
To: Jakub Narebski; +Cc: devel, openembedded-devel, monotone-devel, git
In-Reply-To: <200809131402.11413.jnareb@gmail.com>
On Sat, Sep 13, 2008 at 3:02 PM, Jakub Narebski <jnareb@gmail.com> wrote:
> On Sat, 13 Sep 2008, Felipe Contreras wrote:
>> On Sat, Sep 13, 2008 at 12:45 PM, Jakub Narebski <jnareb@gmail.com> wrote:
>>> "Felipe Contreras" <felipe.contreras@gmail.com> writes:
<snip/>
>>>> After some RFCs on git and monotone mailing lists it seems now that
>>>> the script is going in the right direction.
>>>
>>> When you feel this script to be ready, could you add it to the
>>> "Interaction with other Revision Control Systems" section on
>>> http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
>>> As far as I can see there ain't any Monotone to Git converter on this
>>> list.
>>
>> Ok, done. I think it's ready if you can bare the slowness of the
>> 'checkout' method. The only missing feature is tags, but should be
>> easy to implement.
>
> Thank you.
>
> BTW. did you have any problems with (from what I understand) slightly
> different concept of branches between Monotone and Git?
Monotone can have multiple heads in one single branch, but from what I
understand that mostly happens locally (not on the published repo).
Anyway, If that happens the commits are still there, just dangling
temporarily in no branch.
There isn't much we can do for that situation, except maybe create
branch_n or something. I don't think it's a big problem.
--
Felipe Contreras
^ permalink raw reply
* [PATCH 0/3] Documentation: rebase and workflows
From: Thomas Rast @ 2008-09-13 16:10 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <7v8wtwk4yp.fsf@gitster.siamese.dyndns.org>
Junio C Hamano wrote:
>
First of all, thanks for your excellent criticism of my patch.
(Thanks also to Marcus for spotting the typo, though I eventually
decided to remove the corresponding part again.)
I'm rerolling the entire series, with a few improvements to 3/3, and
following that with an interdiff. 1/3 is almost a complete rewrite.
(I realise that 3/3 is not really related to the first two, so we may
eventually have to split it off the series if it takes more time.)
All snipped comments have been addressed ... hopefully ;-)
> In other words, draw it like this. It is much easier to see what's
> changed and what's unchanged, if the part that hasn't changed stayed
> unchanged in the picture:
[...]
> o---o---o---o---o---o---o---o master
> \ \
> o---o---o---o---o o'--o'--o'--o'--o' subsystem
> \
> *---*---* topic
I had the old one in the other style to emphasise that all commits on
'topic' are "indistinguishable" w.r.t. source. But this indeed makes
for nicer graphs.
> Thomas Rast <trast@student.ethz.ch> writes:
> > +on 'subsystem'. Luckily, 'git-rebase' knows to skip commits that are
> > +textually the same as commits in the upstream. So if you say
>
> There is no luck involved in "git rebase" knowing how to do this -- this
> is by design.
Luckily for the user! :-)
> But more importantly, at this point, there is a break in the flow of
> thought in this section. Step back and read what you wrote, pretending as
> if you are reading the section for the first time, and notice:
[...]
Indeed, you are right. I stole your "merge without rebase" drawing,
and added a paragraph about the reasons for a rebase. However:
> The problem is that the resulting history will keep two copies of the
> morally equivalent commits from the subsystem. You know that, and I know
> that, but the purpose of the document is to explain it to people who do
> not know it yet.
Maybe that's just me, but I always thought the duplication argument
was a bit weak. I think reasons such as "resurrects changes that have
been (presumably for a reason) undone" are far scarier and more likely
to stop users from rebasing. Eventually, I omitted it to keep the
justification paragraph shorter, but if others feel the same, maybe it
should go in.
- Thomas
Thomas Rast (3):
Documentation: new upstream rebase recovery section in git-rebase
Documentation: Refer to git-rebase(1) to warn against rewriting
Documentation: add manpage about workflows
Documentation/Makefile | 2 +-
Documentation/git-commit.txt | 4 +
Documentation/git-filter-branch.txt | 4 +-
Documentation/git-rebase.txt | 129 +++++++++++++-
Documentation/git-reset.txt | 4 +-
Documentation/gitworkflows.txt | 330 +++++++++++++++++++++++++++++++++++
6 files changed, 465 insertions(+), 8 deletions(-)
create mode 100644 Documentation/gitworkflows.txt
^ permalink raw reply
* [PATCH 2/3] Documentation: Refer to git-rebase(1) to warn against rewriting
From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <1221322263-25291-2-git-send-email-trast@student.ethz.ch>
This points readers at the "Recovering from upstream rebase" warning
in git-rebase(1) when we talk about rewriting published history in the
'reset', 'commit --amend', and 'filter-branch' documentation.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
Documentation/git-commit.txt | 4 ++++
Documentation/git-filter-branch.txt | 4 +++-
Documentation/git-reset.txt | 4 +++-
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index eb05b0f..eeba58d 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -144,6 +144,10 @@ It is a rough equivalent for:
------
but can be used to amend a merge commit.
--
++
+You should understand the implications of rewriting history if you
+amend a commit that has already been published. (See the "RECOVERING
+FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
-i::
--include::
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index b0e710d..fed6de6 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -36,7 +36,9 @@ the objects and will not converge with the original branch. You will not
be able to easily push and distribute the rewritten branch on top of the
original branch. Please do not use this command if you do not know the
full implications, and avoid using it anyway, if a simple single commit
-would suffice to fix your problem.
+would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM
+REBASE" section in linkgit:git-rebase[1] for further information about
+rewriting published history.)
Always verify that the rewritten version is correct: The original refs,
if different from the rewritten ones, will be stored in the namespace
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 6abaeac..52aab5e 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -82,7 +82,9 @@ $ git reset --hard HEAD~3 <1>
+
<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad
and you do not want to ever see them again. Do *not* do this if
-you have already given these commits to somebody else.
+you have already given these commits to somebody else. (See the
+"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for
+the implications of doing so.)
Undo a commit, making it a topic branch::
+
--
1.6.0.2.408.g3709
^ permalink raw reply related
* [PATCH 1/3] Documentation: new upstream rebase recovery section in git-rebase
From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <1221322263-25291-1-git-send-email-trast@student.ethz.ch>
Documents how to recover if the upstream that you pull from has
rebased the branches you depend your work on. Hopefully this can also
serve as a warning to potential rebasers.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
See the series leader for discussion.
Documentation/git-rebase.txt | 129 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 124 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 59c1b02..a2f686c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -257,11 +257,10 @@ include::merge-strategies.txt[]
NOTES
-----
-When you rebase a branch, you are changing its history in a way that
-will cause problems for anyone who already has a copy of the branch
-in their repository and tries to pull updates from you. You should
-understand the implications of using 'git-rebase' on a repository that
-you share.
+
+You should understand the implications of using 'git-rebase' on a
+repository that you share. See also RECOVERING FROM UPSTREAM REBASE
+below.
When the git-rebase command is run, it will first execute a "pre-rebase"
hook if one exists. You can use this hook to do sanity checks and
@@ -396,6 +395,126 @@ consistent (they compile, pass the testsuite, etc.) you should use
after each commit, test, and amend the commit if fixes are necessary.
+RECOVERING FROM UPSTREAM REBASE
+-------------------------------
+
+Rebasing (or any other form of rewriting) a branch that others have
+based work on is a bad idea: anyone downstream of it is forced to
+manually fix their history. This section explains how to do the fix
+from the downstream's point of view. The real fix, however, would be
+to avoid rebasing the upstream in the first place.
+
+To illustrate, suppose you are in a situation where someone develops a
+'subsystem' branch, and you are working on a 'topic' that is dependent
+on this 'subsystem'. You might end up with a history like the
+following:
+
+------------
+ o---o---o---o---o---o---o---o---o master
+ \
+ o---o---o---o---o subsystem
+ \
+ *---*---* topic
+------------
+
+If 'subsystem' is rebased against 'master', the following happens:
+
+------------
+ o---o---o---o---o---o---o---o master
+ \ \
+ o---o---o---o---o o'--o'--o'--o'--o' subsystem
+ \
+ *---*---* topic
+------------
+
+If you now continue development as usual, and eventually merge 'topic'
+to 'subsystem', the commits will remain duplicated forever:
+
+------------
+ o---o---o---o---o---o---o---o master
+ \ \
+ o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
+ \ /
+ *---*---*-..........-*--* topic
+------------
+
+Such duplicates are generally frowned upon because they clutter up
+history, making it harder to follow. To clean things up, you need to
+transplant the commits on 'topic' to the new 'subsystem' tip, i.e.,
+rebase 'topic'. This becomes a ripple effect: anyone downstream from
+'topic' is forced to rebase too, and so on!
+
+There are two kinds of fixes, discussed in the following subsections:
+
+Easy case: The changes are literally the same.::
+
+ This happens if the 'subsystem' rebase was a simple rebase and
+ had no conflicts.
+
+Hard case: The changes are not the same.::
+
+ This happens if the 'subsystem' rebase had conflicts, or used
+ `\--interactive` to omit, edit, or squash commits; or if the
+ upstream used one of `commit \--amend`, `reset`, or
+ `filter-branch`.
+
+
+The easy case
+~~~~~~~~~~~~~
+
+Only works if the changes (patch IDs based on the diff contents) on
+'subsystem' are literally the same before and after the rebase.
+
+In that case, the fix is easy because 'git-rebase' knows to skip
+changes that are already present in the new upstream. So if you say
+(assuming you're on 'topic')
+------------
+ git rebase subsystem
+------------
+you will end up with the fixed history
+------------
+ o---o---o---o---o---o---o---o master
+ \
+ o'--o'--o'--o'--o' subsystem
+ \
+ *---*---* topic
+------------
+
+
+The hard case
+~~~~~~~~~~~~~
+
+Things get more complicated if the 'subsystem' changes do not exactly
+correspond to the pre-rebase ones.
+
+NOTE: While an "easy case recovery" sometimes appears to be successful
+ even in the hard case, it may have unintended consequences. For
+ example, a commit that was removed via `git rebase
+ \--interactive` will be **resurrected**!
+
+The idea is to manually tell 'git-rebase' "where the old 'subsystem'
+ended and your 'topic' began", that is, what the old merge-base
+between them was. You will have to find a way to name the last commit
+of the old 'subsystem', for example:
+
+* With the 'subsystem' reflog: after 'git-fetch', the old tip of
+ 'subsystem' is at `subsystem@\{1}`. Subsequent fetches will
+ increase the number. (See linkgit:git-reflog[1].)
+
+* Relative to the tip of 'topic': knowing that your 'topic' has three
+ commits, the old tip of 'subsystem' must be `topic~3`.
+
+You can then transplant the old `subsystem..topic` to the new tip by
+saying (for the reflog case, and assuming you are on 'topic' already):
+------------
+ git rebase --onto subsystem subsystem@{1}
+------------
+
+The ripple effect of a "hard case" recovery is especially bad:
+'everyone' downstream from 'topic' will now have to perform a "hard
+case" recovery too!
+
+
Authors
------
Written by Junio C Hamano <gitster@pobox.com> and
--
1.6.0.2.408.g3709
^ permalink raw reply related
* [PATCH 3/3] Documentation: add manpage about workflows
From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <1221322263-25291-3-git-send-email-trast@student.ethz.ch>
This attempts to make a manpage about workflows that is both handy to
point people at it and as a beginner's introduction.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
Interdiff follows. The important change is that the format-patch
recipe says to use send-email, hopefully keeping people from damaging
their patches via cut&paste.
Unfortunately I still don't know how to make the blocks look right in
manpage format.
Documentation/Makefile | 2 +-
Documentation/gitworkflows.txt | 330 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 331 insertions(+), 1 deletions(-)
create mode 100644 Documentation/gitworkflows.txt
diff --git a/Documentation/Makefile b/Documentation/Makefile
index ded0e40..e33ddcb 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
gitrepository-layout.txt
MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \
- gitdiffcore.txt
+ gitdiffcore.txt gitworkflows.txt
MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt
new file mode 100644
index 0000000..b4b43da
--- /dev/null
+++ b/Documentation/gitworkflows.txt
@@ -0,0 +1,330 @@
+gitworkflows(7)
+===============
+
+NAME
+----
+gitworkflows - An overview of recommended workflows with git
+
+SYNOPSIS
+--------
+git *
+
+
+DESCRIPTION
+-----------
+
+This tutorial gives a brief overview of workflows recommended to
+use, and collaborate with, Git.
+
+While the prose tries to motivate each of them, we formulate a set of
+'rules' for quick reference. Do not always take them literally; you
+should value good reasons higher than following a random manpage to
+the letter.
+
+
+SEPARATE CHANGES
+----------------
+
+As a general rule, you should try to split your changes into small
+logical steps, and commit each of them. They should be consistent,
+working independently of any later commits, pass the test suite, etc.
+
+To achieve this, try to commit your new work at least every couple
+hours. You can always go back and edit the commits with `git rebase
+--interactive` to further improve the history before you publish it.
+
+
+MANAGING BRANCHES
+-----------------
+
+In the following, we will assume there are 'developers', 'testers' and
+'users'. Even if the "Testers" are actually an automated test suite
+and all "Users" are developers themselves, try to think in these terms
+as you follow a software change through its life cycle.
+
+Usually a change evolves in a few steps:
+
+* The developers implement a few iterations until it "seems to work".
+
+* The testers play with it, report bugs, test the fixes, eventually
+ clearing the change for stable releases.
+
+* As the users work with the new feature, they report bugs which will
+ have to be fixed.
+
+In the following sections we discuss some problems that arise from
+such a "change flow", and how to solve them with Git.
+
+We consider a fictional project with (supported) stable branch
+'maint', main testing/development branch 'master' and "bleeding edge"
+branch 'next'. We collectively call these three branches 'main
+branches'.
+
+
+Merging upwards
+~~~~~~~~~~~~~~~
+
+Since Git is quite good at merges, one should try to use them to
+propagate changes. For example, if a bug is fixed, you would want to
+apply the corresponding fix to all main branches.
+
+A quick moment of thought reveals that you cannot do this by merging
+"downwards" to older releases, since that would merge 'all' changes.
+Hence the following:
+
+.Merge upwards
+[caption="Rule: "]
+=====================================
+Always commit your fixes to the oldest supported branch that require
+them. Then (periodically) merge the main branches upwards into each
+other.
+=====================================
+
+This gives a very controlled flow of fixes. If you notice that you
+have applied a fix to e.g. 'master' that is also required in 'maint',
+you will need to cherry-pick it (using linkgit:git-cherry-pick[1])
+downwards. This will happen a few times and is nothing to worry about
+unless you do it all the time.
+
+
+Topic branches
+~~~~~~~~~~~~~~
+
+Any nontrivial feature will require several patches to implement, and
+may get extra bugfixes or improvements during its lifetime. If all
+such commits were in one long linear history chain (e.g., if they were
+all committed directly to 'master'), it becomes very hard to see how
+they belong together.
+
+The key concept here is "topic branches". The name is pretty self
+explanatory, with a minor caveat that comes from the "merge upwards"
+rule above:
+
+.Topic branches
+[caption="Rule: "]
+=====================================
+Make a side branch for every topic. Fork it off at the oldest main
+branch that you will eventually want to merge it into.
+=====================================
+
+Many things can then be done very naturally:
+
+* To get the feature/bugfix into a main branch, simply merge it. If
+ the topic has evolved further in the meantime, merge again.
+
+* If you find you need new features from an 'other' branch to continue
+ working on your topic, merge 'other' to 'topic'. (However, do not
+ do this "just habitually", see below.)
+
+* If you find you forked off the wrong branch and want to move it
+ "back in time", use linkgit:git-rebase[1].
+
+Note that the last two points clash: a topic that has been merged
+elsewhere should not be rebased. See the section on RECOVERING FROM
+UPSTREAM REBASE in linkgit:git-rebase[1].
+
+We should point out that "habitually" (regularly for no real reason)
+merging a main branch into your topics -- and by extension, merging
+anything upstream into anything downstream on a regular basis -- is
+frowned upon:
+
+.Merge to downstream only at well-defined points
+[caption="Rule: "]
+=====================================
+Do not merge to downstream except:
+
+* with a good reason (such as upstream API changes that affect you), or
+
+* at well-defined points such as when an upstream release has been tagged.
+=====================================
+
+Otherwise, the many resulting small merges will greatly clutter up
+history. Anyone who later investigates the history of a file will
+have to find out whether that merge affected the topic in
+development. Linus hates it. An upstream might even inadvertently be
+merged into a "more stable" branch. And so on.
+
+
+Integration branches
+~~~~~~~~~~~~~~~~~~~~
+
+If you followed the last paragraph, you will now have many small topic
+branches, and occasionally wonder how they interact. Perhaps the
+result of merging them does not even work? But on the other hand, we
+want to avoid merging them anywhere "stable" because such merges
+cannot easily be undone.
+
+The solution, of course, is to make a merge that we can undo: merge
+into a throw-away branch.
+
+.Integration branches
+[caption="Rule: "]
+=====================================
+To test the interaction of several topics, merge them into a
+throw-away branch.
+=====================================
+
+If you make it (very) clear that this branch is going to be deleted
+right after the testing, you can even publish this branch, for example
+to give the testers a chance to work with it, or other developers a
+chance to see if their in-progress work will be compatible.
+
+
+SHARING WORK
+------------
+
+After the last section, you should know how to manage topics. In
+general, you will not be the only person working on the project, so
+you will have to share your work.
+
+Roughly speaking, there are two important workflows. Their
+distinguishing mark is whether they can be used to propagate merges.
+Medium to large projects will typically employ some mixture of the
+two:
+
+* "Upstream" in the most general sense 'pushes' changes to the
+ repositor(ies) holding the main history. Everyone can 'pull' from
+ there to stay up to date.
+
+* Frequent contributors, subsystem maintainers, etc. may use push/pull
+ to send their changes upstream.
+
+* The rest -- typically anyone more than one or two levels away from the
+ main maintainer -- send patches by mail.
+
+None of these boundaries are sharp, so find out what works best for
+you.
+
+
+Push/pull
+~~~~~~~~~
+
+There are three main tools that can be used for this:
+
+* linkgit:git-push[1] copies your branches to a remote repository,
+ usually to one that can be read by all involved parties;
+
+* linkgit:git-fetch[1] that copies remote branches to your repository;
+ and
+
+* linkgit:git-pull[1] that does fetch and merge in one go.
+
+Note the last point. Do 'not' use 'git-pull' unless you actually want
+to merge the remote branch.
+
+Getting changes out is easy:
+
+.Push/pull: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+`git push <remote> <branch>` and tell everyone where they can fetch
+from.
+=====================================
+
+You will still have to tell people by other means, such as mail. (Git
+provides the linkgit:request-pull[1] to send preformatted pull
+requests to upstream maintainers to simplify this task.)
+
+If you just want to get the newest copies of the main branches,
+staying up to date is easy too:
+
+.Push/pull: Staying up to date
+[caption="Recipe: "]
+=====================================
+Use `git fetch <remote>` or `git remote update` to stay up to date.
+=====================================
+
+Then simply fork your topic branches from the stable remotes as
+explained earlier.
+
+If you are a maintainer and would like to merge other people's topic
+branches to the main branches, they will typically send a request to
+do so by mail. Such a request might say
+
+-------------------------------------
+Please pull from
+ git://some.server.somewhere/random/repo.git mytopic
+-------------------------------------
+
+In that case, 'git-pull' can do the fetch and merge in one go, as
+follows.
+
+.Push/pull: Merging remote topics
+[caption="Recipe: "]
+=====================================
+`git pull <url> <branch>`
+=====================================
+
+Occasionally, the maintainer may get merge conflicts when he tries to
+pull changes from downstream. In this case, he can ask downstream to
+do the merge and resolve the conflicts themselves (perhaps they will
+know better how to resolve them). It is one of the rare cases where
+downstream 'should' merge from upstream.
+
+
+format-patch/am
+~~~~~~~~~~~~~~~
+
+If you are a contributor that sends changes upstream in the form of
+emails, you should use topic branches as usual (see above). Then use
+linkgit:git-format-patch[1] to generate the corresponding emails
+(highly recommended over manually formatting them because it makes the
+maintainer's life easier).
+
+.format-patch/am: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+* `git format-patch -M upstream..topic` to turn them into preformatted
+ patch files
+* `git send-email --to=<recipient> <patches>`
+=====================================
+
+See the linkgit:git-format-patch[1] and linkgit:git-send-email[1]
+manpages for further usage notes. Also you should be aware that the
+maintainer may impose further restrictions, such as "Signed-off-by"
+requirements.
+
+If the maintainer tells you that your patch no longer applies to the
+current upstream, you will have to rebase your topic (you cannot use a
+merge because you cannot format-patch merges):
+
+.format-patch/am: Keeping topics up to date
+[caption="Recipe: "]
+=====================================
+`git rebase upstream`
+=====================================
+
+You can then fix the conflicts during the rebase. Presumably you have
+not published your topic other than by mail, so rebasing it is not a
+problem.
+
+If you receive such a patch (as maintainer, or perhaps reader of the
+mailing list it was sent to), save the mail to a file and use
+'git-am':
+
+.format-patch/am: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+`git am < patch`
+=====================================
+
+One feature worth pointing out is the three-way merge, which can help
+if you get conflicts because of renames: `git am -3` will use index
+information contained in patches to reconstruct a merge base. See
+linkgit:git-am[1] for other options.
+
+
+SEE ALSO
+--------
+linkgit:gittutorial[7],
+linkgit:git-push[1],
+linkgit:git-pull[1],
+linkgit:git-merge[1],
+linkgit:git-rebase[1],
+linkgit:git-format-patch[1],
+linkgit:git-send-email[1],
+linkgit:git-am[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite.
--
1.6.0.2.408.g3709
^ 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