* Re: [PATCH] git-pickaxe: blame rewritten.
From: Petr Baudis @ 2006-10-12 22:47 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <egmdkv$k33$1@sea.gmane.org>
Dear diary, on Thu, Oct 12, 2006 at 11:55:49PM CEST, I got a letter
where Jakub Narebski <jnareb@gmail.com> said that...
> Junio C Hamano wrote:
>
> > Currently it does what git-blame does, but only faster.
> >
> > More importantly, its internal structure is designed to support
> > content movement (aka cut-and-paste) more easily by allowing
> > more than one paths to be taken from the same commit.
> >
> > Signed-off-by: Junio C Hamano <junkio@cox.net>
> > ---
> >
> > I really hate to do this immediately after writing obituary for
> > annotate, but I had a solid 24-hour to work on git, which is a
> > rare opportunity for me these days, so here it is.
>
> Why not reuse git-annotate name? git-pickaxe doesn't do pickaxe...
I agree that git-pickaxe is wrong, and luckily Junio does too,
apparently.
But please, let's not go right back to the git-annotate / git-blame
situation. It's just confusing to have two tools that do the same thing,
perhaps subtly differently. If it's gonna replace git-blame, it should
either do that right away or live as git-blame2 for some time, but not
play any confusing games with the names.
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)
^ permalink raw reply
* Re: [PATCH 1/2] diff --stat: use asymptotic scaling in graph
From: A Large Angry SCM @ 2006-10-12 22:48 UTC (permalink / raw)
To: Martin Waitz; +Cc: apodtele, git
In-Reply-To: <20061012222703.GA31152@admingilde.org>
Martin Waitz wrote:
> On Thu, Oct 12, 2006 at 03:20:09PM -0700, A Large Angry SCM wrote:
>>> + if (it)
>>> + return it * width / (it + width) + 1;
>>> + else
>>> + return 0;
>> No conditional needed:
>>
>> return it * width / (it + width - 1)
>
> But then it would start scaling much earlier
> (for width 10: at 2 instead of 4).
> This is not bad per se, but different...
>
OK:
return (it * width + (it + width)/2)) / (it + width - 1)
Now it's back at 4. ;-)
^ permalink raw reply
* Re: [PATCH 1/2] diff --stat: use asymptotic scaling in graph
From: Johannes Schindelin @ 2006-10-12 22:52 UTC (permalink / raw)
To: git; +Cc: Martin Waitz, apodtele
In-Reply-To: <452EC625.7050301@gmail.com>
Hi,
On Thu, 12 Oct 2006, A Large Angry SCM wrote:
> Martin Waitz wrote:
> > On Thu, Oct 12, 2006 at 03:20:09PM -0700, A Large Angry SCM wrote:
> > > > + if (it)
> > > > + return it * width / (it + width) + 1;
> > > > + else
> > > > + return 0;
> > > No conditional needed:
> > >
> > > return it * width / (it + width - 1)
> >
> > But then it would start scaling much earlier
> > (for width 10: at 2 instead of 4).
> > This is not bad per se, but different...
> >
>
> OK:
> return (it * width + (it + width)/2)) / (it + width - 1)
>
> Now it's back at 4. ;-)
Am I the only one finding non-linear diffstat ugly and misleading?
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 1/2] diff --stat: use asymptotic scaling in graph
From: apodtele @ 2006-10-12 23:12 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, Martin Waitz
In-Reply-To: <Pine.LNX.4.63.0610130051440.14200@wbgn013.biozentrum.uni-wuerzburg.de>
On 10/12/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Am I the only one finding non-linear diffstat ugly and misleading?
Well, the scaling I propose _is_ linear for small changes. More
importantly, the existing scheme is not linear across the diffs
either. Different stats may _look_ the same but be very different in
size in the existing scheme already. My proposal is invariant across
diff stats. Junio's argument that a change of 30 doesn't look like a
half of 60 is valid, of course. Does anyone really checks this with a
ruler?
^ permalink raw reply
* Re: [PATCH] git-revert with conflicts to behave as git-merge with conflicts
From: Luben Tuikov @ 2006-10-12 23:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vejtdkw4t.fsf@assigned-by-dhcp.cox.net>
--- Junio C Hamano <junkio@cox.net> wrote:
> Luben Tuikov <ltuikov@yahoo.com> writes:
>
> > --- a/git-commit.sh
> > +++ b/git-commit.sh
> > @@ -441,7 +441,7 @@ then
> > elif test "$use_commit" != ""
> > then
> > git-cat-file commit "$use_commit" | sed -e '1,/^$/d'
> > -elif test -f "$GIT_DIR/MERGE_HEAD" && test -f "$GIT_DIR/MERGE_MSG"
> > +elif test -f "$GIT_DIR/MERGE_MSG"
> > then
> > cat "$GIT_DIR/MERGE_MSG"
> > elif test -f "$GIT_DIR/SQUASH_MSG"
>
> If you rely on MERGE_MSG then you would need to clean it after
> commit is done. Currently it does not and checks MERGE_HEAD,
> and cleans up MERGE_HEAD when it is done. MERGE_MSG is not
> cleaned.
It is cleaned in the lines of the patch you deleted, the section
just after the "elif" above:
@@ -607,7 +607,7 @@ then
commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
git-update-ref -m "$rloga: $rlogm" HEAD $commit "$current" &&
- rm -f -- "$GIT_DIR/MERGE_HEAD" &&
+ rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" &&
if test -f "$NEXT_INDEX"
then
mv "$NEXT_INDEX" "$THIS_INDEX"
Luben
^ permalink raw reply
* Re: [PATCH] git-pickaxe: blame rewritten.
From: Junio C Hamano @ 2006-10-12 23:35 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20061012224727.GU20017@pasky.or.cz>
Petr Baudis <pasky@suse.cz> writes:
> But please, let's not go right back to the git-annotate / git-blame
> situation. It's just confusing to have two tools that do the same thing,
> perhaps subtly differently. If it's gonna replace git-blame, it should
> either do that right away or live as git-blame2 for some time, but not
> play any confusing games with the names.
Actually the plan is to make it do _true_ pickaxe, although it
will most likely end up either in dustbin or replace blame.
^ permalink raw reply
* Re: [PATCH] git-pickaxe: blame rewritten.
From: Junio C Hamano @ 2006-10-13 0:06 UTC (permalink / raw)
To: Luben Tuikov; +Cc: git
In-Reply-To: <20061012193107.44651.qmail@web31805.mail.mud.yahoo.com>
Luben Tuikov <ltuikov@yahoo.com> writes:
> Renames are naturally supported?
Didn't I say you can see it yourself by doing this and that?
A short answer is yes. I'll do a re-write-up of algorithm
overview and directions to enhance it in a separate message when
I have time.
One interesting difference is that it can do partial file (line
range). With the "parameter order" fix Linus asked, I can do:
$ git-pickaxe -L 551,554 master commit.c
which would run a lot faster than:
$ git-pickaxe -L 551,560 master commit.c
This is a made-up example, but you would get the idea. In
short, it does not have to dig deeper outside the range
originally you specified.
> ---cut---
> The porcelain format is as follows:
>
> <SHA-1> <orig line> <line> [<num lines>
This is misleading. <num lines> is always shown for the group
head, even if there was another group earlier from the same
commit (otherwise the Porcelain has to buffer the chunk, which
you did not like). Second and subsequent lines in the same
group do not have <num lines>.
> author <name>
> author-mail <email format>
>...
> committer-tz <TZ>
> filename <string>
> summary <string>]
> <TAB><line data>
>
> Where
> <SHA-1> is the SHA-1 of the commit which introduces this line.
> <orig line> it the line number where this line is introduced.
> <line> is the line number of the final file (at SHA-1 commit)
>
> Then, if <SHA-1> is different from the previous line's SHA-1 (if no
> previous then always different), a header follows. It starts by the
> number of lines that this <SHA-1> commit introduces,...
So this description is wrong; <num lines> is not part of the
"extra".
>...
> ---cut----
>
> This kind of makes it slightly clearer.
I deliberately left it vague so that we can add things later to
the header. Porcelains should ignore the fields that they do
not understand, and should not expect these fields listed above
come in the order the above list shows.
Also I deliberately left it vague so that Porcelains can get the
header for the same SHA-1 more than once. This is needed when
we add "ciff" to pick more than one paths from the same commit.
In such a case, most likely we are better off not to repeat
header fields from author...committer-tz and summary but we
would need filename. The expectation to the Porcelains is:
Read one line, which begins with commit object name and two
or three numbers; if it has three numbers, it is the
beginning of a group. Any such "object name" line can be
followed by a header. Read subsequent lines until you get a
line that begins with a <TAB>.
- do not get upset if you see a header field that you do not
understand; you are reading from newer version of blame.
- do not get upset if you see a header for the commit you
have already seen. Some of the header fields can be
updated from the one you have seen the last time, so use
the updated value from the new header.
Lines that begin with a <TAB> is data from the file being
annotated. The object name and headers you saw before this
line annotate it.
So Porcelains need to keep one set of these header fields per
commit object.
^ permalink raw reply
* Re: [PATCH] git-revert with conflicts to behave as git-merge with conflicts
From: Junio C Hamano @ 2006-10-13 0:07 UTC (permalink / raw)
To: Luben Tuikov; +Cc: git
In-Reply-To: <20061012231503.78452.qmail@web31803.mail.mud.yahoo.com>
Luben Tuikov <ltuikov@yahoo.com> writes:
>> If you rely on MERGE_MSG then you would need to clean it after
>> commit is done. Currently it does not and checks MERGE_HEAD,
>> and cleans up MERGE_HEAD when it is done. MERGE_MSG is not
>> cleaned.
>
> It is cleaned in the lines of the patch you deleted, the section
> just after the "elif" above:
Ok, so I can apply that original one with your 'Oops' rolled
into one patch?
^ permalink raw reply
* Re: [PATCH] git-revert with conflicts to behave as git-merge with conflicts
From: Luben Tuikov @ 2006-10-13 0:31 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvempjcwy.fsf@assigned-by-dhcp.cox.net>
--- Junio C Hamano <junkio@cox.net> wrote:
> Luben Tuikov <ltuikov@yahoo.com> writes:
>
> >> If you rely on MERGE_MSG then you would need to clean it after
> >> commit is done. Currently it does not and checks MERGE_HEAD,
> >> and cleans up MERGE_HEAD when it is done. MERGE_MSG is not
> >> cleaned.
> >
> > It is cleaned in the lines of the patch you deleted, the section
> > just after the "elif" above:
>
> Ok, so I can apply that original one with your 'Oops' rolled
> into one patch?
Yes please.
Luben
^ permalink raw reply
* Re: [PATCH 1/2] diff --stat: use asymptotic scaling in graph
From: Nicolas Pitre @ 2006-10-13 0:39 UTC (permalink / raw)
To: A Large Angry SCM; +Cc: Martin Waitz, apodtele, git
In-Reply-To: <452EC625.7050301@gmail.com>
On Thu, 12 Oct 2006, A Large Angry SCM wrote:
> Martin Waitz wrote:
> > On Thu, Oct 12, 2006 at 03:20:09PM -0700, A Large Angry SCM wrote:
> > > > + if (it)
> > > > + return it * width / (it + width) + 1;
> > > > + else
> > > > + return 0;
> > > No conditional needed:
> > >
> > > return it * width / (it + width - 1)
> >
> > But then it would start scaling much earlier
> > (for width 10: at 2 instead of 4).
> > This is not bad per se, but different...
> >
>
> OK:
> return (it * width + (it + width)/2)) / (it + width - 1)
>
> Now it's back at 4. ;-)
Sure, but at this point the original conditional is probably more
efficient.
Nicolas
^ permalink raw reply
* Re: [PATCH] git-pickaxe: blame rewritten.
From: Luben Tuikov @ 2006-10-13 1:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmc1jcz0.fsf@assigned-by-dhcp.cox.net>
--- Junio C Hamano <junkio@cox.net> wrote:
> > ---cut---
> > The porcelain format is as follows:
> >
> > <SHA-1> <orig line> <line> [<num lines>
>
> This is misleading. <num lines> is always shown for the group
> head, even if there was another group earlier from the same
> commit (otherwise the Porcelain has to buffer the chunk, which
Completely understood and always agreed upon.
> you did not like). Second and subsequent lines in the same
> group do not have <num lines>.
Completely understood and always agreed upon.
>
> > author <name>
> > author-mail <email format>
> >...
> > committer-tz <TZ>
> > filename <string>
> > summary <string>]
> > <TAB><line data>
> >
> > Where
> > <SHA-1> is the SHA-1 of the commit which introduces this line.
> > <orig line> it the line number where this line is introduced.
> > <line> is the line number of the final file (at SHA-1 commit)
> >
> > Then, if <SHA-1> is different from the previous line's SHA-1 (if no
> > previous then always different), a header follows. It starts by the
> > number of lines that this <SHA-1> commit introduces,...
>
> So this description is wrong; <num lines> is not part of the
> "extra".
So, it is possible to print
<SHA-1> <orig lineno> <this lineno> <num lines>
TAB<data line>
?
> I deliberately left it vague so that we can add things later to
> the header. Porcelains should ignore the fields that they do
> not understand, and should not expect these fields listed above
> come in the order the above list shows.
If the format changes, then porcelains should change their parsing
algorithms.
> Also I deliberately left it vague so that Porcelains can get the
> header for the same SHA-1 more than once. This is needed when
For different blocks separated by at least one different commit, yes.
But the opposite should not be true.
That is, you start a group, only when the previous commit differs
from this commit.
It would be prudent to print a <num lines> iff a group is started.
> we add "ciff" to pick more than one paths from the same commit.
> In such a case, most likely we are better off not to repeat
> header fields from author...committer-tz and summary but we
> would need filename. The expectation to the Porcelains is:
>
> Read one line, which begins with commit object name and two
> or three numbers; if it has three numbers, it is the
> beginning of a group.
And if it doesn't have three numbers?
Luben
^ permalink raw reply
* On blame/pickaxe
From: Junio C Hamano @ 2006-10-13 1:43 UTC (permalink / raw)
To: Luben Tuikov; +Cc: git
I have something that is tentatively called pickaxe, but that is
different from "diff -S<pickaxe>". The name will need to
change, perhaps to git-blame.
It's quite a while since the original algorithm sketch that led
to the current git-blame was posted here; I suspect that most of
the people recently joined the list haven't seen it. The idea
in there still applies, though...
Here is a re-drawn sketch of how the 'pickaxe' edition of the
algorithm works.
0. Outline.
We track range of lines from a path in one revision. That's
what "-L n,m", "path", and "commit" parameters to the command
are about.
When the program starts, the commit given on the command line is
suspected to be responsible for all lines in the given range.
But being a suspect and determined to be the guilty party are
different things.
The name of the game is "not taking responsibility but passing
the blame to your parents". In other words, "that's not a new
problem I introduced -- it was there before my patch was
applied". You are exonerated for those lines that you can
successfully pass blame to your parent, making that parent a new
suspect for the lines. There will remain lines you cannot pass
blame to anybody else -- you will be determined to be the guilty
party for them. When nobody can pass any more blame to anybody
else, the dance stops and we will know who is guilty for every
line of the input.
1. Data structure.
We keep track of who the current suspect for each line is in the
structure called 'scoreboard'. It is a collection of ranges,
called 'blame_entry'.
Each blame_entry describes which lines (in the final image) it
is about, who the current suspect for the range is, if the
suspect is already known to be guilty, where in the suspected
commit the lines came from (path and line number).
In the 'blame' implementation, a suspect is represented by a
commit object with one path hanging to its util field.
'pickaxe' edition introduces the concept of 'origin', which is a
pair of <commit,path>. We currently do not use more than one
path per commit, but hopefully we will soon.
2. Operation.
First the scoreboard is initialized with a single blame_entry
that makes the path in the commit on the command line the
suspect for all lines.
Then, we repeatedly pick one entry from the scoreboard, and give
a chance to the suspect to exonerate himself, by calling
pass_blame(). The suspect passes the blame to its parents by
updating the scoreboard, removing his name from ranges of lines
he can prove that came from his parent and instead writing that
suspected parent's name. Inside pass_blame(), just before it
returns, if the suspect cannot pass blame for some lines to
anybody else, it becomes guilty for them.
When there is no blame_entry in the scoreboard whose truly
guilty party is still undetermined, we have fully blamed the
input, and the loop finishes.
3. Passing the blame.
You (a <commit,path> tuple) are suspected for introducing
certain lines, and you would want to pass blame to your parent.
How would you do that?
First, you find if your parent has the same path; if not, you
find if between your parent and you there was a rename and find
the original path in the parent. If you are a merge, you do so
for all your parents. The path in the parent and your path may
have many common lines, and if the lines you are the suspect are
the same as the ones in the parent, you can pass the blame,
because these lines were there before you touched them.
How would you find what's common? We run "diff" (diff -u0).
Unified context-0 diff would give something like:
@@ -n,m +l,k @@
-removed
+added
...
In this application, we are not interested in the diff text
itself at all. In fact, we are interested in what's outside the
diff. If the above is output from parent to you, what it tells
us is that lines before your line "l" are the same as lines
before parent's "n", so if the above is the first hunk, you can
say your lines 1..(l-1) came from your parent and you are not
responsible for them. The above hunk also tells us that in your
path, lines after (l+k) are the same as the lines in parent's
lines (n+m); we will know how many such same lines there are
(could be zero) by inspecting the next hunk.
For efficiency reasons, inside pass_blame(), we run just one
diff between the parent and you, and scan the blame_entry for
the same <commit,path> in the scoreboard, and check overlap with
each of them. Suppose we are suspected for these lines:
<---- e ----->
and by looking the diff, we determined the range from one parent
is like this:
<--p--->
Then we can split the blame_entry into three parts:
<-><--p---><->
You are still suspected for the first and the last part of the
original entry, but for the mid-part you successfully passed the
blame to that parent. Depending on how the ranges overlap, this
may split into two, or parent may take blame for the whole range
(i.e. no split). This is computed in blame_overlap().
When done with one parent, if you are a merge, you will then try
to pass the blame on the remaining part that you are still
suspected for to other parents.
The classic 'blame' algorithm stops here, and the current
pickaxe does the same; you take responsibility for the
remainder.
4. Passing more blame.
Instead of taking responsibility for the remainder, there are
other ways to find other people to pass blame on. That's what
the "NEEDSWORK" comment in pass_blame() is about.
A typical example is a change that moves one static C function
from lower part of the file to upper part of the same file,
because you added a new caller in the middle. The path in your
parent and the path in you would look like this:
parent you
A static foo() {
B }
C A
D B
E C
F D
G ... call foo();
static foo() { E
} F
I G
J I
With the common part finding code with diff, you will be able to
pass blames for lines A B C D E F G I J to your parent. You are
truly guilty for introducing "... call foo();". The problem
here is that in addition, you will be blamed for the lines that
implement "static foo() { ... }" at the beginning of your file.
To blame the implementation of foo() to the parent, we could do
something like this:
for each blame_entry that you are still suspected for,
diff those lines (and only those lines) with the parent,
to see if you find a copy. If there is a copy, you can
pass the blame to the parent.
This needs to be limited for non-trivial changes only, though.
For example, one of the typical things you would do is to add one
"else if" clause to a sequence of already existing "if .. else if
.." chain, like this:
if (foo) {
...
}
else if (bar) {
...
+ }
+ else if (baz) {
+ ...
}
You are suspected for these three lines; if the "find copies
again" is allowed to find any insignificant copy, the first line
(closing brace) you introduced could easily be blamed to an
unrelated line anywhere in the parent that match /^\t\}$/. To
prevent such nonsense from happening, we need to limit such
"find copies" attempt to say minimum of N lines (and minimum of
M tokens that consist of non-whitespace, non-punctuation
letters). Also we probably would not want to find a match in
the whole parent but only in the part of the parent that is
removed in the parent-to-you diff.
Another typical example is a code restructuring to move one
function from a file to another file. The same "find copies"
principle, and caveat for small and insignificant copies, apply
to this situation as well. If it is a code movement, the file
that the function moved from needs to be identified, which can
be done by running diff-tree between parent and you -- anything
that was modified or removed is a good candidate to look for
such copies. Again, we probably need to limit the copy-finding
source to the part that was removed from the parent in the diff
to you.
After the operation 3 (Passing the blame) runs, if movement of
lines from another file is detected as in the above sketch, we
will pass blame to an unrelated path in the parent. Some lines
are blamed on the file we started tracking in the parent, and
some other lines are blamed on a different file in the parent.
This is why 'pickaxe' uses <commit,path> tuple (aka 'origin') to
represent a suspect.
All of this sounds quite simple and not so difficult to code,
although rejecting insignificant copies would involve fair
amount of heuristic tweaking like I needed to do while working
on the rename detection.
^ permalink raw reply
* Re: [PATCH] git-pickaxe: blame rewritten.
From: Junio C Hamano @ 2006-10-13 1:45 UTC (permalink / raw)
To: Luben Tuikov; +Cc: git
In-Reply-To: <20061013010402.99837.qmail@web31814.mail.mud.yahoo.com>
Luben Tuikov <ltuikov@yahoo.com> writes:
> That is, you start a group, only when the previous commit differs
> from this commit.
>
> It would be prudent to print a <num lines> iff a group is started.
Yes. I think the current code does that.
>> we add "ciff" to pick more than one paths from the same commit.
>> In such a case, most likely we are better off not to repeat
>> header fields from author...committer-tz and summary but we
>> would need filename. The expectation to the Porcelains is:
>>
>> Read one line, which begins with commit object name and two
>> or three numbers; if it has three numbers, it is the
>> beginning of a group.
>
> And if it doesn't have three numbers?
It can still have header if we wanted to say some more details
about the line. What's the problem?
^ permalink raw reply
* [PATCH 2/2] git-repack: -b to pass --delta-base-offset
From: Junio C Hamano @ 2006-10-13 5:35 UTC (permalink / raw)
To: GIT Mailing List; +Cc: Nicolas Pitre
In-Reply-To: <11607177011745-git-send-email-junkio@cox.net>
This new option makes the resulting pack express the delta base
with more compact "offset" format.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Documentation/git-repack.txt | 8 +++++++-
git-repack.sh | 1 +
2 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index 49f7e0a..5f5530d 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -9,7 +9,7 @@ objects into pack files.
SYNOPSIS
--------
-'git-repack' [-a] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
+'git-repack' [-a] [-b] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
DESCRIPTION
-----------
@@ -35,6 +35,12 @@ OPTIONS
about people fetching via dumb protocols from it. Use
with '-d'.
+-b::
+ Pass the `--delta-base-offset` to `git pack-objects`;
+ see gitlink:git-pack-objects[1]. Do not use this option
+ if you want the repository to be accessible by older
+ versions of git.
+
-d::
After packing, if the newly created packs make some
existing packs redundant, remove the redundant packs.
diff --git a/git-repack.sh b/git-repack.sh
index b525fc5..25dae5e 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -14,6 +14,7 @@ do
-n) no_update_info=t ;;
-a) all_into_one=t ;;
-d) remove_redundant=t ;;
+ -b) extra="$extra --delta-base-offset" ;;
-q) quiet=-q ;;
-f) no_reuse_delta=--no-reuse-delta ;;
-l) local=--local ;;
--
1.4.3.rc2.g51ca
^ permalink raw reply related
* [PATCH 1/2] pack-objects: document --delta-base-offset option
From: Junio C Hamano @ 2006-10-13 5:35 UTC (permalink / raw)
To: GIT Mailing List; +Cc: Nicolas Pitre
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Documentation/git-pack-objects.txt | 13 ++++++++++++-
builtin-pack-objects.c | 2 +-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index d4661dd..5788709 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -9,7 +9,7 @@ git-pack-objects - Create a packed archi
SYNOPSIS
--------
[verse]
-'git-pack-objects' [-q] [--no-reuse-delta] [--non-empty]
+'git-pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
[--local] [--incremental] [--window=N] [--depth=N]
[--revs [--unpacked | --all]*] [--stdout | base-name] < object-list
@@ -110,6 +110,17 @@ base-name::
This flag tells the command not to reuse existing deltas
but compute them from scratch.
+--delta-base-offset::
+ A packed archive can express base object of a delta as
+ either 20-byte object name or as an offset in the
+ stream, but older version of git does not understand the
+ latter. By default, git-pack-objects only uses the
+ former format for better compatibility. This option
+ allows the command to use the latter format for
+ compactness. Depending on the average delta chain
+ length, this option typically shrinks the resulting
+ packfile by 3-5 per-cent.
+
Author
------
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index ee5f031..41e1e74 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -15,7 +15,7 @@ #include "list-objects.h"
#include <sys/time.h>
#include <signal.h>
-static const char pack_usage[] = "git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] [--revs [--unpacked | --all]*] [--stdout | base-name] <ref-list | <object-list]";
+static const char pack_usage[] = "git-pack-objects [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] [--revs [--unpacked | --all]*] [--stdout | base-name] <ref-list | <object-list]";
struct object_entry {
unsigned char sha1[20];
--
1.4.3.rc2.g51ca
^ permalink raw reply related
* Re: [PATCH] git-pickaxe: blame rewritten.
From: Junio C Hamano @ 2006-10-13 5:35 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0610120854440.3952@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Thu, 12 Oct 2006, Junio C Hamano wrote:
>> +
>> +SYNOPSIS
>> +--------
>> +'git-pickaxe' [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [--] <file> [<rev>]
>
> Btw, could we please get rid of this horrible command line syntax.
>
> Pretty much _every_ other git command takes the form
>
> git cmd [<rev>] [--] <path>
>
> but for some reason annotate and blame (and now pickaxe) do it the wrong
> way around, and do
>
> git cmd [--] <path> [<rev>]
>
> which is just irritating to somebody who has grown very used to being able
> to specify revisions first.
>
> (I'd actually also like to have a range-modifier, so that I could do
>
> git annotate --since=2.weeks.ago v2.6.18.. <path>
>
> that didn't go back beyond a certain point, so the command line syntax
> actually _does_ matter - even if we don't support that now, having the
> regular command line syntax means that we -could- support it some day).
>
> Linus
So here it is. I did not think "-n 20" would make sense for
this application so the code does not do anything about it.
This will be parked on "pu" for now.
-- >8 --
[PATCH] git-pickaxe: minimally use revision machinery.
This rewrites pickaxe argument parser to use revision machinery,
so that you can say something like:
git pickaxe --since=2.weeks master commit.c
git pickaxe -L 20,40 v1.4.0..master -- commit.c
The traditional parameter order (path first then optional rev)
is supported but cannot be mixed with revision limiting
parameters.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Documentation/git-pickaxe.txt | 2 +-
builtin-pickaxe.c | 221 ++++++++++++++++++++++++++++++++---------
2 files changed, 173 insertions(+), 50 deletions(-)
diff --git a/Documentation/git-pickaxe.txt b/Documentation/git-pickaxe.txt
index 7f30cdf..7685bd0 100644
--- a/Documentation/git-pickaxe.txt
+++ b/Documentation/git-pickaxe.txt
@@ -7,7 +7,7 @@ git-pickaxe - Show what revision and aut
SYNOPSIS
--------
-'git-pickaxe' [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [--] <file> [<rev>]
+'git-pickaxe' [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [<rev>] [--] <file>
DESCRIPTION
-----------
diff --git a/builtin-pickaxe.c b/builtin-pickaxe.c
index 0e26308..0aa4565 100644
--- a/builtin-pickaxe.c
+++ b/builtin-pickaxe.c
@@ -11,13 +11,14 @@ #include "commit.h"
#include "tree-walk.h"
#include "diff.h"
#include "diffcore.h"
+#include "revision.h"
#include "xdiff-interface.h"
#include <time.h>
#include <sys/time.h>
static char pickaxe_usage[] =
-"git-pickaxe [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [--] file [commit]\n"
+"git-pickaxe [-c] [-l] [-t] [-f] [-n] [-p] [-L n,m] [-S <revs-file>] [commit] [--] file\n"
" -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
" -l, --long Show long commit SHA1 (Default: off)\n"
" -t, --time Show raw timestamp (Default: off)\n"
@@ -109,7 +110,8 @@ static void coalesce(struct scoreboard *
for (o = 0, i = 0; i < num; i++) {
if (o &&
ent[o-1]->suspect == ent[i]->suspect &&
- ent[o-1]->s_lno + ent[o-1]->num_lines == ent[i]->s_lno) {
+ ent[o-1]->s_lno + ent[o-1]->num_lines == ent[i]->s_lno &&
+ ent[o-1]->guilty == ent[i]->guilty) {
ent[o-1]->num_lines += ent[i]->num_lines;
free(ent[i]);
continue;
@@ -220,7 +222,8 @@ static void process_u0_diff(void *state_
struct chunk *chunk;
int off1, off2, len1, len2;
-if(DEBUG) fprintf(stderr, "%.*s", (int) len, line);
+ if (DEBUG)
+ fprintf(stderr, "%.*s", (int) len, line);
if (len < 4 || line[0] != '@' || line[1] != '@')
return;
@@ -256,17 +259,23 @@ static struct patch *get_patch(struct or
mmfile_t file_p, file_o;
xdemitcb_t ecb;
char type[10];
-
-if(DEBUG) fprintf(stderr, "get patch %.8s %.8s\n",
- sha1_to_hex(parent->commit->object.sha1),
- sha1_to_hex(origin->commit->object.sha1));
-
- file_p.ptr = read_sha1_file(parent->blob_sha1, type,
- (unsigned long *) &file_p.size);
- file_o.ptr = read_sha1_file(origin->blob_sha1, type,
- (unsigned long *) &file_o.size);
- if (!file_p.ptr || !file_o.ptr)
+ char *blob_p, *blob_o;
+
+ if (DEBUG) fprintf(stderr, "get patch %.8s %.8s\n",
+ sha1_to_hex(parent->commit->object.sha1),
+ sha1_to_hex(origin->commit->object.sha1));
+
+ blob_p = read_sha1_file(parent->blob_sha1, type,
+ (unsigned long *) &file_p.size);
+ blob_o = read_sha1_file(origin->blob_sha1, type,
+ (unsigned long *) &file_o.size);
+ file_p.ptr = blob_p;
+ file_o.ptr = blob_o;
+ if (!file_p.ptr || !file_o.ptr) {
+ free(blob_p);
+ free(blob_o);
return NULL;
+ }
xpp.flags = XDF_NEED_MINIMAL;
xecfg.ctxlen = 0;
@@ -280,6 +289,8 @@ if(DEBUG) fprintf(stderr, "get patch %.8
state.ret->num = 0;
xdl_diff(&file_p, &file_o, &xpp, &xecfg, &ecb);
+ free(blob_p);
+ free(blob_o);
return state.ret;
}
@@ -417,11 +428,12 @@ static int pass_blame_to_parent(struct s
for (i = 0; i < patch->num; i++) {
struct chunk *chunk = &patch->chunks[i];
-if(DEBUG) fprintf(stderr,
- "plno = %d, tlno = %d, "
- "same as parent up to %d, resync %d and %d\n",
- plno, tlno,
- chunk->same, chunk->p_next, chunk->t_next);
+ if (DEBUG)
+ fprintf(stderr,
+ "plno = %d, tlno = %d, "
+ "same as parent up to %d, resync %d and %d\n",
+ plno, tlno,
+ chunk->same, chunk->p_next, chunk->t_next);
blame_chunk(sb, tlno, plno, chunk->same, target, parent);
plno = chunk->p_next;
tlno = chunk->t_next;
@@ -434,7 +446,8 @@ if(DEBUG) fprintf(stderr,
}
#define MAXPARENT 16
-static void pass_blame(struct scoreboard *sb, struct origin *origin)
+static void pass_blame(struct scoreboard *sb, struct origin *origin,
+ struct rev_info *revs)
{
int i, parent_ix;
struct commit *commit = origin->commit;
@@ -448,8 +461,15 @@ static void pass_blame(struct scoreboard
for (parent_ix = 0, parent = commit->parents;
parent_ix < MAXPARENT && parent;
parent = parent->next, parent_ix++) {
- if (parse_commit(parent->item))
+ struct commit *p = parent->item;
+
+ if (parse_commit(p))
+ continue;
+ if (p->object.flags & UNINTERESTING)
continue;
+ if (revs->max_age != -1 && p->date < revs->max_age)
+ continue;
+
porigin = find_origin(sb, parent->item, origin->path);
if (!porigin)
porigin = find_rename(sb, parent->item, origin);
@@ -485,14 +505,9 @@ static void pass_blame(struct scoreboard
* Optionally run "ciff" to find copies from parents' files here
*/
- /* Take responsibility for the remaining entries */
- for (i = 0; i < sb->num_entries; i++)
- if (!sb->entries[i]->guilty &&
- sb->entries[i]->suspect == origin)
- sb->entries[i]->guilty = 1;
}
-static void assign_blame(struct scoreboard *sb)
+static void assign_blame(struct scoreboard *sb, struct rev_info *revs)
{
while (1) {
int i;
@@ -506,7 +521,13 @@ static void assign_blame(struct scoreboa
if (!suspect)
return; /* all done */
- pass_blame(sb, suspect);
+ pass_blame(sb, suspect, revs);
+
+ /* Take responsibility for the remaining entries */
+ for (i = 0; i < sb->num_entries; i++)
+ if (!sb->entries[i]->guilty &&
+ sb->entries[i]->suspect == suspect)
+ sb->entries[i]->guilty = 1;
}
}
@@ -829,23 +850,29 @@ static void find_alignment(struct scoreb
max_digits = lineno_width(longest_dst_lines);
}
+static int has_path_in_work_tree(const char *path)
+{
+ struct stat st;
+ return !lstat(path, &st);
+}
+
int cmd_pickaxe(int argc, const char **argv, const char *prefix)
{
- const char *path = argv[1];
- unsigned char sha1[20];
+ struct rev_info revs;
+ const char *path;
struct scoreboard sb;
struct origin *o;
struct blame_entry *ent;
- int i, seen_dashdash;
+ int i, seen_dashdash, unk;
long bottom, top, lno;
int output_option = 0;
const char *revs_file = NULL;
- const char *final_commit_name = "HEAD";
+ const char *final_commit_name = NULL;
char type[10];
bottom = top = 0;
seen_dashdash = 0;
- for (i = 1; i < argc; i++) {
+ for (unk = i = 1; i < argc; i++) {
const char *arg = argv[i];
if (*arg != '-')
break;
@@ -887,28 +914,121 @@ int cmd_pickaxe(int argc, const char **a
break;
}
else
+ argv[unk++] = arg;
+ }
+
+ /* We have collected options unknown to us in argv[1..unk]
+ * which are to be passed to revision machinery if we are
+ * going to do the "bottom" procesing.
+ *
+ * The remaining are:
+ *
+ * (1) if seen_dashdash, its either
+ * "-options -- <path>" or
+ * "-options -- <path> <rev>".
+ * but the latter is allowed only if there is no
+ * options that we passed to revision machinery.
+ *
+ * (2) otherwise, we may have "--" somewhere later and
+ * might be looking at the first one of multiple 'rev'
+ * parameters (e.g. " master ^next ^maint -- path").
+ * See if there is a dashdash first, and give the
+ * arguments before that to revision machinery.
+ * After that there must be one 'path'.
+ *
+ * (3) otherwise, its one of the three:
+ * "-options <path> <rev>"
+ * "-options <rev> <path>"
+ * "-options <path>"
+ * but again the first one is allowed only if
+ * there is no options that we passed to revision
+ * machinery.
+ */
+
+ if (seen_dashdash) {
+ /* (1) */
+ if (argc <= i)
+ usage(pickaxe_usage);
+ path = argv[i];
+ if (i + 1 == argc - 1) {
+ if (unk != 1)
+ usage(pickaxe_usage);
+ argv[unk++] = argv[i + 1];
+ }
+ else if (i + 1 != argc)
+ /* garbage at end */
usage(pickaxe_usage);
}
+ else {
+ int j;
+ for (j = i; !seen_dashdash && j < argc; j++)
+ if (!strcmp(argv[j], "--"))
+ seen_dashdash = j;
+ if (seen_dashdash) {
+ if (seen_dashdash + 1 != argc - 1)
+ usage(pickaxe_usage);
+ path = argv[seen_dashdash + 1];
+ for (j = i; j < seen_dashdash; j++)
+ argv[unk++] = argv[j];
+ }
+ else {
+ /* (3) */
+ path = argv[i];
+ if (i + 1 == argc - 1) {
+ final_commit_name = argv[i + 1];
+
+ /* if (unk == 1) we could be getting
+ * old-style
+ */
+ if (unk == 1 && !has_path_in_work_tree(path)) {
+ path = argv[i + 1];
+ final_commit_name = argv[i];
+ }
+ }
+ else if (i != argc - 1)
+ usage(pickaxe_usage); /* garbage at end */
- /* argv[i] is filename, argv[i+1] if exists is the commit */
- if (i >= argc)
- usage(pickaxe_usage);
- path = argv[i++];
- if (!seen_dashdash) {
- struct stat st;
- if (lstat(path, &st))
- die("cannot stat path %s: %s", path, strerror(errno));
+ if (!has_path_in_work_tree(path))
+ die("cannot stat path %s: %s",
+ path, strerror(errno));
+ }
}
- if (i == argc - 1)
- final_commit_name = argv[i];
- else if (i != argc)
- usage(pickaxe_usage);
+ if (final_commit_name)
+ argv[unk++] = final_commit_name;
+ /* Now we got rev and path. We do not want the path pruning
+ * but we may want "bottom" processing.
+ */
+ argv[unk] = NULL;
+
+ init_revisions(&revs, NULL);
+ setup_revisions(unk, argv, &revs, "HEAD");
memset(&sb, 0, sizeof(sb));
- if (get_sha1(final_commit_name, sha1) ||
- !(sb.final = lookup_commit_reference(sha1)))
- die("no such commit %s", final_commit_name);
+
+ /* There must be one and only one positive commit in the
+ * revs->pending array.
+ */
+ for (i = 0; i < revs.pending.nr; i++) {
+ struct object *obj = revs.pending.objects[i].item;
+ if (obj->flags & UNINTERESTING)
+ continue;
+ if (obj->type != OBJ_COMMIT)
+ die("Non commit %s?",
+ revs.pending.objects[i].name);
+ if (sb.final)
+ die("More than one commit to dig from %s and %s?",
+ revs.pending.objects[i].name,
+ final_commit_name);
+ sb.final = (struct commit *) obj;
+ final_commit_name = revs.pending.objects[i].name;
+ }
+ /* If we have bottom, this will mark the ancestors of the
+ * bottom commits we would reach while traversing as
+ * uninteresting.
+ */
+ prepare_revision_walk(&revs);
+
o = find_origin(&sb, sb.final, path);
if (!o)
die("no such path %s in %s", path, final_commit_name);
@@ -939,7 +1059,7 @@ int cmd_pickaxe(int argc, const char **a
die("reading graft file %s failed: %s",
revs_file, strerror(errno));
- assign_blame(&sb);
+ assign_blame(&sb, &revs);
coalesce(&sb);
@@ -947,6 +1067,9 @@ int cmd_pickaxe(int argc, const char **a
find_alignment(&sb, &output_option);
output(&sb, output_option);
-
+ free((void *)sb.final_buf);
+ for (i = 0; i < sb.num_entries; i++)
+ free(sb.entries[i]);
+ free(sb.entries);
return 0;
}
--
1.4.3.rc2.g51ca
^ permalink raw reply related
* [PATCH] git-fetch: Allow branch."branchname".remote=.
From: Santi Béjar @ 2006-10-13 7:50 UTC (permalink / raw)
To: Git Mailing List
Signed-off-by: Santi Béjar <sbejar@gmail.com>
---
git-parse-remote.sh | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 679f73c..617d022 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -187,6 +187,15 @@ get_remote_refs_for_push () {
}
get_remote_refs_for_fetch () {
+ if [ "$#,$1" = "1,." ] ;
+ then
+ curr_branch=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||')
+ branch_remote=$(git-repo-config --get "branch.$curr_branch.remote")
+ if [ "$branch_remote" = "." ]
+ then
+ set . $(git-repo-config --get-all "branch.${curr_branch}.merge")
+ fi
+ fi
case "$#" in
0)
die "internal error: get-remote-refs-for-fetch." ;;
--
1.4.3.rc2.ga442
^ permalink raw reply related
* Re: On blame/pickaxe
From: Junio C Hamano @ 2006-10-13 7:54 UTC (permalink / raw)
To: git
In-Reply-To: <7vr6xddm7h.fsf@assigned-by-dhcp.cox.net>
In an earlier message, I talked about pickaxe data structure
that has potential for blaming more than one paths in a single
revision.
I was talking about the future enhancements, but it turns out
that there is a corner case that the feature is already needed
using the classic blame algorithm, and running blame shows its
limitation through.
The scenario is like this:
- initial has two files A and B
- branch left renames A to C and adds stuff at the top.
- branch right renames B to C and adds stuff at the bottom.
- left and right is merged and leaves one file, C, by taking
what both branches did.
- annotate C from the top.
The parts that came from A and B in the initial revision should
be assigned to these files in the initial commit. If you look
at the blame output, you will see it fails to do so. pickaxe
gives what is expected.
-- >8 --
#!/bin/sh
if test -d .git
then
echo 'please run this in a fresh empty directory'
exit
fi
git init-db
for i in 1 2 3 4 5 6 7 8 9 ; do echo line line line $i ; done >A
for i in A B C D E F G H I ; do echo line line line $i ; done >B
git add A B
git commit --author='Initial <initial@author>' -m initial
git branch right
git branch left
# Left
git checkout left
for i in 1 2 3; do echo added by left; done >C
cat A >>C
rm -f A B
git update-index --add --remove A B C
git commit --author='Left <left@branch>' -m Left
# Right
git checkout right
cat B >C
for i in 1 2 3; do echo added by right; done >>C
rm -f A B
git update-index --add --remove A B C
git commit --author='Right <right@branch>' -m Right
# Merge them; this should fail which is expected
git pull . left
{
git cat-file blob :3:C
git cat-file blob :2:C
} >C
git update-index C
git commit --author='Merge <merge@branch>' -m 'Changes are merged.'
rm -f C~*
echo blame
git blame -f -n -t C
echo pickaxe
git pickaxe -f -n -t C
^ permalink raw reply
* Re: [PATCH] git-fetch: Allow branch."branchname".remote=.
From: Junio C Hamano @ 2006-10-13 7:56 UTC (permalink / raw)
To: Santi Béjar; +Cc: git
In-Reply-To: <87y7rk3b9n.fsf@gmail.com>
Santi Béjar <sbejar@gmail.com> writes:
<nothing>
> Signed-off-by: Santi Béjar <sbejar@gmail.com>
What does it do?
^ permalink raw reply
* Re: [PATCH] git-fetch: Allow branch."branchname".remote=.
From: Santi @ 2006-10-13 9:08 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vpscwd4ya.fsf@assigned-by-dhcp.cox.net>
2006/10/13, Junio C Hamano <junkio@cox.net>:
> Santi Béjar <sbejar@gmail.com> writes:
>
>
> What does it do?
>
It allows to define that the default remote repository is the local
one. For example, in git.git you could have:
[branch "next"]
remote="."
merge=master
so the default merge in the next branch is the master branch in the
local repository.
Santi
^ permalink raw reply
* t4015-diff-whitespace broken on cygwin's bash
From: Alex Riesen @ 2006-10-13 9:12 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
[-- Attachment #1: Type: text/plain, Size: 252 bytes --]
It seem to cut off the last CR from text-here. I.e.
cat <<EOF >x
...
CR at end^M
EOF
becomes just "CR at end" in the output file, that is ^M (aka CR) stripped.
The attached workaround worked for me, but is, as usual, too ugly to
sign it off.
[-- Attachment #2: fix-t4015-diff-whitespace.patch --]
[-- Type: application/xxxxx, Size: 1115 bytes --]
^ permalink raw reply
* Re: [PATCH] git-fetch: Allow branch."branchname".remote=.
From: Johannes Schindelin @ 2006-10-13 11:27 UTC (permalink / raw)
To: Santi; +Cc: Junio C Hamano, git
In-Reply-To: <8aa486160610130208s67ea0746o8a54910860b3fb78@mail.gmail.com>
Hi,
On Fri, 13 Oct 2006, Santi wrote:
> For example, in git.git you could have:
>
> [branch "next"]
> remote="."
> merge=master
>
> so the default merge in the next branch is the master branch in the
> local repository.
There is a subtle problem here. Up until now, "remote" meant a short cut.
You either had a file with that name in .git/remotes/ or .git/branches, or
an entry in the config (remote.<name>.url).
You use it differently here, designating the URL instead of the remote.
I'd rather have it point to a real remote.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] git-fetch: Allow branch."branchname".remote=.
From: Jakub Narebski @ 2006-10-13 12:39 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.63.0610131324090.14200@wbgn013.biozentrum.uni-wuerzburg.de>
Johannes Schindelin wrote:
> There is a subtle problem here. Up until now, "remote" meant a short cut.
> You either had a file with that name in .git/remotes/ or .git/branches, or
> an entry in the config (remote.<name>.url).
Not exactly. "git-pull . <branch>" and "git-peek-remote ." meant use
_current_ repository. "." as remote name means "current", i.e. local
repository.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH] git-fetch: Allow branch."branchname".remote=.
From: Johannes Schindelin @ 2006-10-13 12:53 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Santi Béjar, git
In-Reply-To: <ego1ea$tsn$1@sea.gmane.org>
Hi,
On Fri, 13 Oct 2006, Jakub Narebski wrote:
> Johannes Schindelin wrote:
>
> > There is a subtle problem here. Up until now, "remote" meant a short cut.
> > You either had a file with that name in .git/remotes/ or .git/branches, or
> > an entry in the config (remote.<name>.url).
>
> Not exactly. "git-pull . <branch>" and "git-peek-remote ." meant use
> _current_ repository. "." as remote name means "current", i.e. local
> repository.
>From Documentation/git-pull.txt:
SYNOPSIS
--------
'git-pull' <options> <repository> <refspec>...
It says "repository", not "remote". As for the name "git-peek-remote":
yes, it is a short cut for "remote repository".
The thing is, if you say you pull "from a remote", then it is not
sufficient to specify just a URL of a repository. You also have to specify
a branch.
For git-peek-remote and git-ls-remote, you only need a URL.
If you mix the usage, people get as confused as with the terms "pull",
"update" and "merge".
Ciao,
Dscho
^ permalink raw reply
* Re: t4015-diff-whitespace broken on cygwin's bash
From: Johannes Schindelin @ 2006-10-13 12:56 UTC (permalink / raw)
To: Alex Riesen; +Cc: git, Junio C Hamano
In-Reply-To: <81b0412b0610130212uca8371fg92db5081a8175cb3@mail.gmail.com>
Hi,
On Fri, 13 Oct 2006, Alex Riesen wrote:
> It seem to cut off the last CR from text-here. I.e.
>
> cat <<EOF >x
> ...
> CR at end^M
> EOF
>
> becomes just "CR at end" in the output file, that is ^M (aka CR) stripped.
I can confirm this problem. Strange. I always thought that "cat << EOF"
was meant to copy verbatim. I think it is a bug in cygwin.
The only sensible workaround I can think of is to put the files into a
directory t4015/ like t4013 does.
Ciao,
Dscho
^ permalink raw reply
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