Git development
 help / color / mirror / Atom feed
* Re: [PATCH] transplant: move a series of commits to a different parent
From: Johannes Sixt @ 2007-06-25  7:16 UTC (permalink / raw)
  To: git
In-Reply-To: <9C4338DC-0C4A-4981-9EC9-2417513F629D@zib.de>

Steffen Prohaska wrote:
> 
> On Jun 23, 2007, at 11:04 PM, Alex Riesen wrote:
> 
> >> git-transplant.sh <onto> <from> <to>
> >>
> >> transplant starts with the contents of <onto> and puts on top of
> >> it the contents of files if they are touched by the series of
> >> commits <from>..<to>.  If a commit touches a file the content of
> >> this file is taken as it is in the commit. No merging is
> >> performed. Original authors, commiters, and commit messages are
> >> preserved.
> >>
> > [...]
> > # detached head
> > git checkout $(git rev-parse onto) && git format-patch --stdout
> > --full-index from..to|git am -3
> 
> No. This one tries to apply the _changes_ between from..to. What I
> need is the resulting _content_ of files modified between from..to.

Install a graft that points the parent of "from" to "onto", then run
git-filter-branch. Like so:

 $ echo "$(git-rev-parse from^0) $(git-rev-parse onto^0)" \
        > .git/info/grafts
 $ git-filter-branch new-to onto..to

(no filters necessary).

-- Hannes

^ permalink raw reply

* Re: unexpected git-cherry-pick conflict
From: Gerrit Pape @ 2007-06-25  7:18 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.64.0706131543140.4059@racer.site>

On Wed, Jun 13, 2007 at 03:43:48PM +0100, Johannes Schindelin wrote:
> On Wed, 13 Jun 2007, Gerrit Pape wrote:
> > On Wed, Jun 13, 2007 at 01:58:51PM +0100, Johannes Schindelin wrote:
> > > On Wed, 13 Jun 2007, Gerrit Pape wrote:
> > > >  $ git checkout master
> > > >  Switched to branch "master"
> > > >  $ git cherry-pick 8ddc4d5
> > > >  CONFLICT (file/directory): There is a directory with name link in
> > > >  8ddc4d5... file. Added link as link~HEAD
> > > 
> > > Here you _still_ have the file in master. So that conflict is really 
> > > expected, since a cherry-pick will only do a three-way merge.
> > 
> > git-cherry-pick(1) states
> >  Given one existing commit, apply the change the patch introduces, and
> >  record a new commit that records it. This requires your working tree to
> >  be clean (no modifications from the HEAD commit).
> > 
> > The patch introduced by the commit that's cherry-pick'ed has nothing to
> > do with the link or new directory, it just changes 'file'
> > 
> >  $ git show 8ddc4d5
> >  commit 8ddc4d59444a362261e10a3b22324818f5dd2fa7
> >  Author: Gerrit Pape <pape@smarden.org>
> >  Date:   Wed Jun 13 09:10:30 2007 +0000
> >  
> >      file
> >  
> >  diff --git a/file b/file
> >  index 257cc56..3bd1f0e 100644
> >  --- a/file
> >  +++ b/file
> >  @@ -1 +1,2 @@
> >   foo
> >  +bar
> >  $ 
> > 
> > The patch applies to master just fine.  Where's my thinking wrong?
> 
> Hmm. Indeed. Thanks for clearing that up. Will work on it later.

Hi, did you get to this yet?, not to stress you, just to make sure we
don't forget about it.

Thanks, Gerrit.

^ permalink raw reply

* [PATCH] git-merge: record merge strategy in the log message on auto resolved merges
From: Gerrit Pape @ 2007-06-25  7:16 UTC (permalink / raw)
  To: Junio C Hamano, git

If a strategy module auto resolved the merge cleanly, record the used
strategy in the log message, e.g.:

  Merge branch 'maint' using strategy ours

Signed-off-by: Gerrit Pape <pape@smarden.org>
---

> I personally find this useful especially for the 'ours' strategy.
Resend, maybe it's not that interesting, there was no followup when sent
the first time.

 git-merge.sh |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/git-merge.sh b/git-merge.sh
index 981d69d..b661f74 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -440,7 +440,8 @@ done
 if test '' != "$result_tree"
 then
     parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
-    result_commit=$(printf '%s\n' "$merge_msg" | git-commit-tree $result_tree $parents) || exit
+    result_commit=$(printf '%s\n' "$merge_msg using strategy $wt_strategy" |
+	git-commit-tree $result_tree $parents) || exit
     finish "$result_commit" "Merge made by $wt_strategy."
     dropsave
     exit 0
-- 
1.5.2

^ permalink raw reply related

* Re: most commonly used git commands?
From: Michael S. Tsirkin @ 2007-06-25  7:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Michael S. Tsirkin, git
In-Reply-To: <7vlke833wr.fsf@assigned-by-dhcp.pobox.com>

> Quoting Junio C Hamano <gitster@pobox.com>:
> Subject: Re: most commonly used git commands?
> 
> "Michael S. Tsirkin" <mst@dev.mellanox.co.il> writes:
> 
> > I did this by mistake:
> >
> > $git fet linux-2.6
> > git: 'fet' is not a git-command
> >
> > The most commonly used git commands are:
> >    add     Add file contents to the changeset to be committed next
> >    apply   Apply a patch on a git index file and a working tree
> > (use 'git help -a' to get a list of all installed git commands)
> >
> > why does git say that add and apply are most commonly used git commands?
> 
> Perhaps they are most commonly used by the person who came up
> with that list first ;-)?
> 
> I think "add" deserves to be there, I am not sure "apply" is.

git add is supposed to be rare, no?
That's why git commit lists file additions/removals ...

My list is typically
git checkout
git commit
git pull
git push
git rebase
git reset
git update-index

Maybe it makes sense to take the list from
"Main porcelain commands" section in git manual?

-- 
MST

^ permalink raw reply

* Re: most commonly used git commands?
From: Junio C Hamano @ 2007-06-25  7:10 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: git
In-Reply-To: <20070625064017.GA2839@mellanox.co.il>

"Michael S. Tsirkin" <mst@dev.mellanox.co.il> writes:

> I did this by mistake:
>
> $git fet linux-2.6
> git: 'fet' is not a git-command
>
> The most commonly used git commands are:
>    add     Add file contents to the changeset to be committed next
>    apply   Apply a patch on a git index file and a working tree
> (use 'git help -a' to get a list of all installed git commands)
>
> why does git say that add and apply are most commonly used git commands?

Perhaps they are most commonly used by the person who came up
with that list first ;-)?

I think "add" deserves to be there, I am not sure "apply" is.

^ permalink raw reply

* Re: [PATCH] git-submodule: provide easy way of adding new submodules
From: Junio C Hamano @ 2007-06-25  7:09 UTC (permalink / raw)
  To: skimo; +Cc: git, Lars Hjemli
In-Reply-To: <20070624210607.GC997MdfPADPa@greensroom.kotnet.org>

Sven Verdoolaege <skimo@kotnet.org> writes:

> To make a submodule effectively usable, the path and
> a URL where the submodule can be cloned need to be stored
> in .gitmodules.  This subcommand takes care of setting
> this information after cloning the new submodule.
> Only the index is updated, so, if needed, the user may still
> change the URL or switch to a different branch of the submodule
> before committing.
>
> Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
> ---
> On Sun, Jun 24, 2007 at 10:50:48AM -0700, Junio C Hamano wrote:
>> Sven Verdoolaege <skimo@kotnet.org> writes:
>> 
>> > They're different because submodule update (which also calls module_clone)
>> > is performed on a module that already exists in the repo and
>> > was therefore checked out by git as an empty directory.  If you
>> > add a new submodule, then there is no reason for the subdirectory
>> > to exist already.
>> 
>> Ah, you are absolutely right.  Thanks for the clarification.
>> 
>> By the way, when I have to say "thanks for the clarification", I
>> think it is an indication that the relevant parts of the code
>> need a bit of commenting ;-).
>
> How's this ?

I am not sure about the usefulness of "-b branch" thing myself,
but other than that, looks very sane to me.

Lars?

^ permalink raw reply

* Re: [PATCH] git-svnimport: added explicit merge graph option -G
From: Junio C Hamano @ 2007-06-25  7:05 UTC (permalink / raw)
  To: Stas Maximov; +Cc: git
In-Reply-To: <437777.72821.qm@web43141.mail.sp1.yahoo.com>

Stas Maximov <smaximov@yahoo.com> writes:

> From fd83a4e003802b6cb4dc8a2d058310f235f65e17 Mon Sep 17 00:00:00 2001
> From: Stas Maximov <smaximov@yahoo.com>
> Date: Sat, 23 Jun 2007 09:06:30 -0700
> Subject: [PATCH] git-svnimport: added explicit merge graph option -G
>
> Allows explicit merge graph information to be provided. Each line
> of merge graph file must contain a pair of SVN revision numbers
> separated by space. The first number is child (merged to) SVN rev
> number and the second is the parent (merged from) SVN rev number.
> Comments can be started with '#' and continue to the end of line.
> Empty and space-only lines are allowed and will be ignored.
>
> Signed-off-by: Stas Maximov <smaximov@yahoo.com>
>
> diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
> old mode 100644
> new mode 100755
> index e97d15e..c902b64

Executable documentation ;-)?

> diff --git a/git-svnimport.perl b/git-svnimport.perl
> index f459762..113b252 100755
> --- a/git-svnimport.perl
> +++ b/git-svnimport.perl
> ...
> @@ -80,6 +81,39 @@ if ($opt_M) {
>      unshift (@mergerx, qr/$opt_M/);
>  }
>  
> +
> +# merge_graph will be used for finding all parent SVN revisions for a given SVN
> +# revision. It will be implemented as a hash of hashes. First level hash will
> +# be keyed with the child SVN rev and contain a hash keyed with the parent SVN
> +# revisions. Values of the second level hash are not important (1 will be
> +# used). The keys will be used to store the parent revs for uniqueness.
> +our %merge_graph;
> +
> +
> +# read-in the explicit merge graph specified with -G option
> +if ($opt_G) {
> +    open(F,"cat $opt_G | sed -e 's/#.*\$//' -e '/^\$/d' |") or
> +        die("Can not open $opt_G");
> +    while(<F>) {
> +        chomp;
> +        die "ERROR: invalid line in $opt_G: $_" unless /^\s*(\d+)\s+(\d+)\s*$/;
> +        # $merge_graph{child_rev}{parent_rev} = 1;
> +        $merge_graph{$1}{$2} = 1;
> +    }

Many issues here.

 * Don't cat a single file into a pipe;
 * Don't invoke "sed" when you are writing in Perl;
 * Statement modifier with side effects is extremely hard to read;
 * Does the order of parents for a single child matter?  Do you
   ever have a look-up that says "I have a SVN child Id, and
   another commit Id.  Check quickly if the latter is one of the
   parents of the child"?  Otherwise nested hash is probably not
   the right data structure to use.

How about...

	open F, '<', $opt_G
        	or die("Cannot open '$opt_G'");
	while (<F>) {
		chomp;
		s/#.*//;
                next if ($_ eq '');
                if (/^\s*(\d+)\s+(\d+)\s*$/) {
			$merge_graph{$1} ||= [];
                        push @{$merge_graph{$1}}, $2;
                } else {
                	die "$opt_G:$. :malformed input $_\n";
		}
	}

You would need to change merge_graph_get_parents() as well, if
you do this; see below.

> +    close(F);
> +}
> +
> +
> +# Given an SVN revision (string), finds all its parent SVN revisions in the
> +# merge graph.
> +sub merge_graph_get_parents($)
> +{
> +    my $child_svnrev = shift;
> +    my @parents = keys(%{$merge_graph{$child_svnrev}});
> +    return @parents;
> +}

Can the caller ever call this with a svnrev not in $opt_G file?
Do we want to protect ourselves against it?

	sub merge_graph_get_parents {
		my $child_svnrev = shift;
		if (exists $merge_graph{$child_svnrev}) {
                	return @{$merge_graph{$child_svnrev}};
		}
                return ();
	}

> +
> +
>  # Absolutize filename now, since we will have chdir'ed by the time we
>  # get around to opening it.
>  $opt_A = File::Spec->rel2abs($opt_A) if $opt_A;
> @@ -356,6 +390,24 @@ if ($opt_A) {
>  
>  open BRANCHES,">>", "$git_dir/svn2git";
>  
> +
> +# Given an SVN revision (string), returns all corresponding GIT revisions.
> +#
> +# Note that it is possible that one SVN revision needs to be split into two or
> +# more GIT commits (revision). For example, this will happen if SVN user
> +# commits two branches at once.
> +sub svnrev_to_gitrevs($)
> +{
> +    my $svnrev = shift;
> +    my @gitrevs;
> +    for my $b (keys(%branches)) {
> +        push (@gitrevs, $branches{$b}{$svnrev})
> +            if defined($branches{$b}{$svnrev});
> +    }
> +    return @gitrevs;
> +}

Hmph.  The computation cost for this is proportional to the
number of branches on the SVN side?  Would that be a problem in
real-life (not an objection, but am just wondering.  "Not a
problem, because..." is an acceptable answer).

> @@ -815,6 +867,19 @@ sub commit {
>                      }
>                  }
>              }
> +
> +            # add parents from explicit merge graph (-G)
> +            {
> +                my @svnpars = merge_graph_get_parents($revision);
> +                foreach my $svnp (@svnpars) {
> +                    my @gitpars = svnrev_to_gitrevs($svnp);
> +                    foreach my $gitp (@gitpars) {
> +                        push (@parents, $gitp);
> +                        #print OUT "MG: $svnp -merge-> $revision\n";
> +                    }
> +                }
> +            }
> +

Leftover debugging print?

> From 7008a13f1fe00fdbd90be6a12ad1197dceedaebb Mon Sep 17 00:00:00 2001
> From: Stas Maximov <smaximov@yahoo.com>
> Date: Sun, 24 Jun 2007 14:23:29 -0700
> Subject: [PATCH] Fixed permissions of Documentation/git-svnimport.txt
>
>
> Signed-off-by: Stas Maximov <smaximov@yahoo.com>
>
> diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
> old mode 100755
> new mode 100644

Nah.  Fold this part to the previous commit and start the
document as a nonexecutable file from the beginning.

^ permalink raw reply

* most commonly used git commands?
From: Michael S. Tsirkin @ 2007-06-25  6:40 UTC (permalink / raw)
  To: Junio C Hamano, git

I did this by mistake:

$git fet linux-2.6
git: 'fet' is not a git-command

The most commonly used git commands are:
   add     Add file contents to the changeset to be committed next
   apply   Apply a patch on a git index file and a working tree
(use 'git help -a' to get a list of all installed git commands)

why does git say that add and apply are most commonly used git commands?

-- 
MST

^ permalink raw reply

* Re: qgit: Annotate hundreds of files at terrific speed ;-)
From: Nanako Shiraishi @ 2007-06-25  6:35 UTC (permalink / raw)
  To: Marco Costalba; +Cc: GIT
In-Reply-To: <e5bfff550706242259s143fe874mf82736426e94ecba@mail.gmail.com>


>> Marco Costalba <mcostalba@gmail.com> wrote:
>
> - filtering, ie selecting with the mouse some lines and getting a
> subset of the file history that modified at least one of that lines is
> not possible.

I often use "git blame -L'/regexp/,/regexp/'" (you can use line
numbers there, too).  Is this different from what you talk above?

-- 
しらいし ななこ http://ivory.ap.teacup.com/nanako3/

----------------------------------------------------------------------
Get a free email address with REAL anti-spam protection.
http://www.bluebottle.com

^ permalink raw reply

* Re: [PATCH] Add git-save script
From: しらいしななこ @ 2007-06-25  6:32 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: GIT
In-Reply-To: <Pine.LNX.4.64.0706231605160.4059@racer.site>

Quoting Johannes Schindelin <Johannes.Schindelin@gmx.de>:

> Hi,
> 
> On Sat, 23 Jun 2007, Nanako Shiraishi wrote:
> 
> > Here is how to use my script:
> > 
> >     $ git save
> >     $ git pull
> >     $ git save restore
> 
> This use case has been discussed often, under the name "git-stash".
> 
> Ciao,
> Dscho

Thank you for your comments.  Do you suggest I rename the script to git-stash and re-submit after fixing according to Junio's comments?

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/

----------------------------------------------------------------------
Finally - A spam blocker that actually works.
http://www.bluebottle.com

^ permalink raw reply

* Re: [PATCH] diff: round down similarity index
From: Junio C Hamano @ 2007-06-25  6:18 UTC (permalink / raw)
  To: René Scharfe; +Cc: David Kastrup, Johannes Schindelin, Git Mailing List
In-Reply-To: <467EEEE6.3090100@lsrfire.ath.cx>

René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:

> +static int similarity_index(struct diff_filepair *p)
> +{
> +	int result = p->score * 100.0 / MAX_SCORE;
> +
> +	/* Paranoia: guard against floating point rounding errors. */
> +	if (p->score == MAX_SCORE)
> +		result = 100;
> +	else if (result == 100)
> +		result = 99;
> +
> +	return result;
> +}

Why not simply do this?

        static int similarity_index(struct diff_filepair *p)
        {
                if (p->score == MAX_SCORE)
                        return 100;
                return p->score * 100 / MAX_SCORE;
        }

MAX_SCORE and p->score run up to 60000 and we assume int is at
least 32-bit, so I do not think there is no risk of overflowing.

^ permalink raw reply

* Re: DWIM ref names for push/fetch
From: Junio C Hamano @ 2007-06-25  6:10 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706242234250.4740@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> I was actually thinking exclusively of the matching of strings like "HEAD" 
> or "origin/next" or "master" to refs from the list of available refs. It 
> seems to me like the push code does a better job of handling the same 
> sorts of things that get_sha1() handles.
>
> In particular, the handling of "refs/my/funny/thing" is really wrong: it 
> gets treated as refs/heads/refs/my/funny/thing.

git-parse-remote.sh::canon_refs_list_for_fetch() seems to say
otherwise, though.

 - When unspecified, or explicitly spelled HEAD, take HEAD;
 - Anything that begins with refs/, use it as is;
 - Anything that begins with heads/, tags/, remotes/, assume
   it is a branch, a tag, or a tracking branch;
 - Otherwise assume a branch;

So I suspect refs/my/funny/thing is covered by the second rule.

But I do agree "otherwise assume a branch" part has huge room
for improvement.  Especially...

> I think that "origin/next" 
> should also be assumed to be refs/remotes/origin/next instead of 
> refs/heads/origin/next, at least if you have refs/remotes/origin/ and not 
> refs/heads/origin/.

... I think that makes perfect sense -- the code should
interpret your example as a request to start using a new
tracking branch refs/remotes/origin/next.

^ permalink raw reply

* Re: qgit: Annotate hundreds of files at terrific speed ;-)
From: Marco Costalba @ 2007-06-25  5:59 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Git Mailing List
In-Reply-To: <20070624230851.GN17393@spearce.org>

On 6/25/07, Shawn O. Pearce <spearce@spearce.org> wrote:
> Marco Costalba <mcostalba@gmail.com> wrote:
> > You get _all_ the hundreds (more then 800) of revisions of this
> > monster history annotated in the time it takes *other* ;-) tools to
>
> By "other tools" do you mean git-blame?  ;-)
>

git-blame has some powerful features, like the possibility to follow
renames, and is fast enough for what it has to do, ie annotate _one_
file.

But missing to annotate all the file's history has its drawbacks for
using in a GUI tool, some clear, other not so clear:

- browsing among file revisions it's slow because after each user
'click' another annotation cycle should start from scratch (clear
issue).

- jumping from one file revision to another keeping the same mouse
selection or view (current line at the top of the view) is not
possible in general case without parsing all the annotations between
the two revisions.

- filtering, ie selecting with the mouse some lines and getting a
subset of the file history that modified at least one of that lines is
not possible.


So when 'git log --follow' patch will be mainstream I think current
qgit 'git log'  based annotation will be superior to a git-blame based
interface under any point.

Regarding speed IMHO it is already faster, ie it takes already the
same or _less_ time to qgit to annotate all the 800 and more file's
revisions of git Makefile then to git-blame/git-gui to annotate _one_
of them.

Note that this is not a problem of implementation, but of algorithm.
Simply, the best algorithm to annotate one file is different from the
best one to annotate all of them. Another thing I've experienced is
that on old files in big repos (kernel/sched.c) the time to get the
file history its much bigger then time to annotate them.


Sure, in git-blame annotation it's incremental, you don't have to wait
the end of history loading to start to show stuff. I've used it, but,
probably a my limit, I really don't start to analyze what I have until
git-blame has finished.

So *for me*, the incremental blaming it's more or less a kind of fancy
progress bar, when you really care to search some blaming info.


Regarding the CVS oriented annotation of qgit it's simply a problem
that I have no space to show the commit when the user selects a line.
In git-gui the half bottom screen space is dedicated to that, in qgit
the half top space is instead reserved for file history. Anyhow in
qgit you can double click on any annotation line and the history will
jump to the corresponding revision, from there (right click->popup
menu) you can sync the other tabs so to see full commit and patch.

I'm thinking on a way to add a quick view of commit log message when
the user clicks/selects/something-else on a line (in qgit memory there
is already all the needed info, remember, annotation it's git-log
based), but the screen space it's an issue.


Marco

^ permalink raw reply

* Re: [PATCH] diff: round down similarity index
From: David Kastrup @ 2007-06-25  5:08 UTC (permalink / raw)
  To: René Scharfe; +Cc: Junio C Hamano, Johannes Schindelin, Git Mailing List
In-Reply-To: <467EEEE6.3090100@lsrfire.ath.cx>

René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:

> +static int similarity_index(struct diff_filepair *p)
> +{
> +	int result = p->score * 100.0 / MAX_SCORE;

Use floor(p->score ... MAX_SCORE) here: I don't think that C otherwise
specifies a preferred way of rounding on float->int conversions.

> +	/* Paranoia: guard against floating point rounding errors. */
> +	if (p->score == MAX_SCORE)
> +		result = 100;
> +	else if (result == 100)
> +		result = 99;

Also, p->score itself must be calculated by truncating.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply

* Re: parsecvs fails even on simple input
From: Shawn O. Pearce @ 2007-06-25  4:59 UTC (permalink / raw)
  To: Keith Packard; +Cc: Roman Kagan, Al Viro, git
In-Reply-To: <1182720667.13289.41.camel@neko.keithp.com>

Keith Packard <keithp@keithp.com> wrote:
> On Fri, 2007-06-22 at 15:36 +0400, Roman Kagan wrote:
> >  Wouldn't it be better to teach parsecvs
> > to speak git-fast-import language instead?
> 
> Avoiding fork/exec is rather important for parsecvs perforamance.

That sort of thing is the entire point behind fast-import.  Its only
one fork+exec to setup the fast-import "daemon" in the background,
and you do everything over a pipe to its stdin.  Including forcing
it to finish its current packfile and open a new one on the next
object (the `checkpoint` command).

fast-import is fast, its input language is fairly simple, and its
quite stable.  And its only one fork+exec.  That's peanuts compared
to the disk IO involved in any sizable import process.

-- 
Shawn.

^ permalink raw reply

* Re: parsecvs fails even on simple input
From: Keith Packard @ 2007-06-24 21:31 UTC (permalink / raw)
  To: Roman Kagan; +Cc: keithp, Al Viro, git
In-Reply-To: <20070622113625.GD12473@rkagan.sw.ru>

[-- Attachment #1: Type: text/plain, Size: 633 bytes --]

On Fri, 2007-06-22 at 15:36 +0400, Roman Kagan wrote:

> The problem is the following: after that commit parsecvs tries to add
> objects to the git tree on its own via calls to libgit; however, in
> between it runs git-pack-objects.  Thus objects move to pack files
> without libgit being aware of it; this results in 'ivalid object'
> errors.

Sticking a call to reprepare_packed_git() after the pack creation fixes
this nicely.

>  Wouldn't it be better to teach parsecvs
> to speak git-fast-import language instead?

Avoiding fork/exec is rather important for parsecvs perforamance.

-- 
keith.packard@intel.com

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: Darcs
From: Dan Chokola @ 2007-06-25  4:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, Martin Langhoff, Bu Bacoo, git
In-Reply-To: <alpine.LFD.0.98.0706241657540.3593@woody.linux-foundation.org>

On 6/24/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Sun, 24 Jun 2007, Dan Chokola wrote:
> >
> > What I have noticed is a lot of nitpicking, of which I'm guilty, too. The
> > issue Linus brought up about Darcs and versioning is not one I typically see
> > surface in real life. Users usually complain about some _release_ version
> > or, "I updated last week."
>
> Actually, in the kernel, we are getting quite a lot out of "git bisect",
> and people throw git SHA1's around to describe where they are, or a
> particular commit.
>
> Which never happened with BK.
>
> So I think that the _ability_ to name revisions easily across different
> uses is quite important, because it then drives behaviour.
>

I wholeheartedly agree it's important as far as the big picture of SCM
is concerned. Though I will say that the kernel development is an
extreme case, where there's a huge number of developers and incredibly
fast development where matching features are needed from the SCM. And
I love how Git is born out of this extreme case, as it leads to a lot
of great features that often scale down, too. But some of them matter
less to, say, a small, well-integrated team of 5 or 10 people. And an
idealistic model like the one offered by Darcs might even work better
there since corner cases don't show up often.

I'm spoiled by Git and the fact that it has these great abilities and
features that set it apart, and I'd love everyone to use it. But I'd
like people to know that many attributes of Git and other DSCMs don't
differ all that much. (Please don't call me ugly and stupid. ;) And
actually, this is something of a selling point, because it makes it
Git seem cozy and familiar.

So, relating back to the original post, and extending on Linus'
'academic' analogy, Darcs is like a thesis project from university
that proves how DSCM can be done scientifically. Git is grown-up Darcs
that proves how DSCM can be done practically. The bottom line is the
foundations of DSCM, cheap branching, easy merging, and the like, can
be done very similarly in either Darcs or Git, so moving from one to
the other leaves you with a largely familiar set of commands.

> Without it, you'll never notice you need it. With it, you start wondering
> how others handle it.
>

Git really does have a way of spoiling its users (I don't know how
CVS/SVN users live), no argument here.

-Daniel "Puzzles" Chokola

^ permalink raw reply

* Re: DWIM ref names for push/fetch
From: Daniel Barkalow @ 2007-06-25  3:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v3b0gq4id.fsf@assigned-by-dhcp.cox.net>

On Sun, 24 Jun 2007, Junio C Hamano wrote:

> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > Is this difference simply due to the different languages the matching 
> > portions of these were originally written in?
> 
> If anything, the semantics on the fetch side is _very_ much
> intentional and is done deliberately that way to be usable.  
> 
> On the other hand, push started as "matching only", and then
> "match tail part of the name" as an afterthought.  It was so
> afterthought that it had an idiotic behaviour of independently
> match the source and destination side even when there is no
> colon, which was fixed only recently.
> 
> So if you would want to match fetch and push, you should not
> change the semantics on fetch to match what push does, as the
> latter was done pretty much without design.
> 
> Having said that, I think fetch and push DWIMmery are
> fundamentally different, especially when you do not have a
> colon.  push without storing anything on the receiving end would
> not make any sense whatsoever, but fetch without using tracking
> branches does make perfect sense, so push does pretend dst side
> has what matched with src side pattern, while fetch treats no
> colon pattern as not storing.  IOW, even if we wanted to reuse
> the code on both sides as much as possible, I suspect we would
> need to have details different between them.

The no-colon handling is right as it is, as well as the semantics of 
fetching without tracking refs.

I was actually thinking exclusively of the matching of strings like "HEAD" 
or "origin/next" or "master" to refs from the list of available refs. It 
seems to me like the push code does a better job of handling the same 
sorts of things that get_sha1() handles.

In particular, the handling of "refs/my/funny/thing" is really wrong: it 
gets treated as refs/heads/refs/my/funny/thing. I think that "origin/next" 
should also be assumed to be refs/remotes/origin/next instead of 
refs/heads/origin/next, at least if you have refs/remotes/origin/ and not 
refs/heads/origin/.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [PATCH] diff: round down similarity index
From: René Scharfe @ 2007-06-25  1:29 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, David Kastrup, Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0706250026400.4059@racer.site>

Johannes Schindelin schrieb:
> Hi,
> 
> On Mon, 25 Jun 2007, Johannes Schindelin wrote:
> 
>> On Mon, 25 Jun 2007, Ren� Scharfe wrote:
>>
>>> Rounding down the printed (dis)similarity index allows us to use
>>> "100%" as a special value that indicates complete rewrites and
>>> fully equal file contents, respectively.
>>>
>>> [...]
>>>
>>> +static int similarity_index(struct diff_filepair *p)
>>> +{
>>> +	int result = p->score * 100.0 / MAX_SCORE;
>>> +
>>> +	/* Paranoia: guard against floating point rounding errors. */
>>> +	if (p->score == MAX_SCORE)
>>> +		result = 100;
>>> +	else if (result == 100)
>>> +		result = 99;
>>> +
>>> +	return result;
>>> +}

>> Besides, AFAIR p->score is not even calculated if the files are identical, 
>> because that hits a different code path.

True, ->score is set to MAX_SCORE for identical files by a different
code path than the one that actually compares the contents and
calculates a score.  That doesn't matter for printing the "similarity
index nn%" line etc., though.  Or is there a way for identical files to
end up with a ->score of 0 (or some other value != MAX_SCORE) that I missed?

In any case, the patch doesn't change the way the score is calculated,
i.e. its value is the same as before.  It only changes how it is displayed.

René

^ permalink raw reply

* Re: problem pushing repository
From: Jakub Narebski @ 2007-06-25  1:01 UTC (permalink / raw)
  To: git
In-Reply-To: <20070624234759.GO17393@spearce.org>

Shawn O. Pearce wrote:

> Heh, sure.  I wrote that "stock" bash completion package, but at
> this point I largely consider it to be "complete and stable" and
> therefore don't put a lot of effort into it anymore.

One thing that annoys me greatly (and I think I use newest completion)
is that sometimes _filename_ completion gets confused on the '.' separating
basename and extension, and instead of completing extension it adds another
dot to make range operator '..' and triec to complete branch name, even if
basename is _not_ any branch name.

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* [PATCH 2/2] Teach rebase an interactive mode
From: Johannes Schindelin @ 2007-06-25  0:11 UTC (permalink / raw)
  To: Junio C Hamano, Brian Gernhardt; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706241204450.4059@racer.site>


Don't you just hate the fact sometimes, that git-rebase just applies
the patches, without any possibility to edit them, or rearrange them?
With "--interactive", git-rebase now lets you edit the list of patches,
so that you can reorder, edit and delete patches.

Such a list will typically look like this:

	pick deadbee The oneline of this commit
	pick fa1afe1 The oneline of the next commit
	...

By replacing the command "pick" with the command "edit", you can amend
that patch and/or its commit message, and by replacing it with "squash"
you can tell rebase to fold that patch into the patch before that.

It is derived from the script sent to the list in
<Pine.LNX.4.63.0702252156190.22628@wbgn013.biozentrum.uni-wuerzburg.de>

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	Junio wrote:

	> Is today my "nitpick shell scripts day"? ;-)

	Seems so ;-)

	In addition to your comments, I actually fixed the reflog
	entries, since they picked up the comment from rebase
	(without -i).

	Also, the last updating step was not necessary at all, since
	rebase -i works on the same branch all the time.

	Furthermore, your comment that a check for an empty $DONE file
	is not sufficient applies as well for the check that $TODO
	contains some actions. Both are fixed.

	The continue without a loop in that function was (as you probably
	suspected) a refactoring leftover.

	All other suggestions were included as-are.

 Documentation/git-rebase.txt  |   85 ++++++++++++-
 Makefile                      |    2 +-
 git-rebase--interactive.sh    |  289 +++++++++++++++++++++++++++++++++++++++++
 git-rebase.sh                 |   12 ++-
 t/t3404-rebase-interactive.sh |  163 +++++++++++++++++++++++
 5 files changed, 546 insertions(+), 5 deletions(-)
 create mode 100755 git-rebase--interactive.sh
 create mode 100755 t/t3404-rebase-interactive.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 0c00090..2e3363a 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -8,7 +8,8 @@ git-rebase - Forward-port local commits to the updated upstream head
 SYNOPSIS
 --------
 [verse]
-'git-rebase' [-v] [--merge] [-C<n>] [--onto <newbase>] <upstream> [<branch>]
+'git-rebase' [-i | --interactive] [-v | --verbose] [--merge] [-C<n>]
+	[--onto <newbase>] <upstream> [<branch>]
 'git-rebase' --continue | --skip | --abort
 
 DESCRIPTION
@@ -208,6 +209,10 @@ OPTIONS
 	context exist they all must match.  By default no context is
 	ever ignored.
 
+-i, \--interactive::
+	Make a list of the commits which are about to be rebased.  Let the
+	user edit that list before rebasing.
+
 include::merge-strategies.txt[]
 
 NOTES
@@ -226,9 +231,83 @@ pre-rebase hook script for an example.
 You must be in the top directory of your project to start (or continue)
 a rebase.  Upon completion, <branch> will be the current branch.
 
-Author
+INTERACTIVE MODE
+----------------
+
+Rebasing interactively means that you have a chance to edit the commits
+which are rebased.  You can reorder the commits, and you can
+remove them (weeding out bad or otherwise unwanted patches).
+
+The interactive mode is meant for this type of workflow:
+
+1. have a wonderful idea
+2. hack on the code
+3. prepare a series for submission
+4. submit
+
+where point 2. consists of several instances of
+
+a. regular use
+ 1. finish something worthy of a commit
+ 2. commit
+b. independent fixup
+ 1. realize that something does not work
+ 2. fix that
+ 3. commit it
+
+Sometimes the thing fixed in b.2. cannot be amended to the not-quite
+perfect commit it fixes, because that commit is buried deeply in a
+patch series.  That is exactly what interactive rebase is for: use it
+after plenty of "a"s and "b"s, by rearranging and editing
+commits, and squashing multiple commits into one.
+
+Start it with the last commit you want to retain as-is:
+
+	git rebase -i <after-this-commit>
+
+An editor will be fired up with all the commits in your current branch
+(ignoring merge commits), which come after the given commit.  You can
+reorder the commits in this list to your heart's content, and you can
+remove them.  The list looks more or less like this:
+
+-------------------------------------------
+pick deadbee The oneline of this commit
+pick fa1afe1 The oneline of the next commit
+...
+-------------------------------------------
+
+The oneline descriptions are purely for your pleasure; `git-rebase` will
+not look at them but at the commit names ("deadbee" and "fa1afe1" in this
+example), so do not delete or edit the names.
+
+By replacing the command "pick" with the command "edit", you can tell
+`git-rebase` to stop after applying that commit, so that you can edit
+the files and/or the commit message, amend the commit, and continue
+rebasing.
+
+If you want to fold two or more commits into one, replace the command
+"pick" with "squash" for the second and subsequent commit.  If the
+commits had different authors, it will attribute the squashed commit to
+the author of the last commit.
+
+In both cases, or when a "pick" does not succeed (because of merge
+errors), the loop will stop to let you fix things, and you can continue
+the loop with `git rebase --continue`.
+
+For example, if you want to reorder the last 5 commits, such that what
+was HEAD~4 becomes the new HEAD. To achieve that, you would call
+`git-rebase` like this:
+
+----------------------
+$ git rebase -i HEAD~5
+----------------------
+
+And move the first patch to the end of the list.
+
+Authors
 ------
-Written by Junio C Hamano <junkio@cox.net>
+Written by Junio C Hamano <junkio@cox.net> and
+Johannes E. Schindelin <johannes.schindelin@gmx.de>
 
 Documentation
 --------------
diff --git a/Makefile b/Makefile
index a98e27a..4ea5e45 100644
--- a/Makefile
+++ b/Makefile
@@ -204,7 +204,7 @@ SCRIPT_SH = \
 	git-fetch.sh \
 	git-ls-remote.sh \
 	git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
-	git-pull.sh git-rebase.sh \
+	git-pull.sh git-rebase.sh git-rebase--interactive.sh \
 	git-repack.sh git-request-pull.sh git-reset.sh \
 	git-sh-setup.sh \
 	git-tag.sh git-verify-tag.sh \
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
new file mode 100755
index 0000000..ab36572
--- /dev/null
+++ b/git-rebase--interactive.sh
@@ -0,0 +1,289 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Johannes E. Schindelin
+
+# SHORT DESCRIPTION
+#
+# This script makes it easy to fix up commits in the middle of a series,
+# and rearrange commits.
+#
+# The original idea comes from Eric W. Biederman, in
+# http://article.gmane.org/gmane.comp.version-control.git/22407
+
+USAGE='(--continue | --abort | --skip | [--onto <branch>] <upstream> [<branch>])'
+
+. git-sh-setup
+require_work_tree
+
+DOTEST="$GIT_DIR/.dotest-merge"
+TODO="$DOTEST"/todo
+DONE="$DOTEST"/done
+STRATEGY=
+VERBOSE=
+
+warn () {
+	echo "$*" >&2
+}
+
+require_clean_work_tree () {
+	# test if working tree is dirty
+	git rev-parse --verify HEAD > /dev/null &&
+	git update-index --refresh &&
+	git diff-files --quiet &&
+	git diff-index --cached --quiet HEAD ||
+	die "Working tree is dirty"
+}
+
+ORIG_REFLOG_ACTION="$GIT_REFLOG_ACTION"
+
+comment_for_reflog () {
+	case "$ORIG_REFLOG_ACTION" in
+	''|rebase*)
+		GIT_REFLOG_ACTION="rebase -i ($1)"
+		export GIT_REFLOG_ACTION
+	esac
+}
+
+mark_action_done () {
+	sed -e 1q < "$TODO" >> "$DONE"
+	sed -e 1d < "$TODO" >> "$TODO".new
+	mv -f "$TODO".new "$TODO"
+}
+
+make_patch () {
+	parent_sha1=$(git rev-parse --verify "$1"^ 2> /dev/null)
+	git diff "$parent_sha1".."$1" > "$DOTEST"/patch
+}
+
+die_with_patch () {
+	make_patch "$1"
+	die "$2"
+}
+
+pick_one () {
+	case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
+	git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
+	parent_sha1=$(git rev-parse --verify $sha1^ 2>/dev/null)
+	current_sha1=$(git rev-parse --verify HEAD)
+	if [ $current_sha1 = $parent_sha1 ]; then
+		git reset --hard $sha1
+		sha1=$(git rev-parse --short $sha1)
+		warn Fast forward to $sha1
+	else
+		git cherry-pick $STRATEGY "$@"
+	fi
+}
+
+do_next () {
+	read command sha1 rest < "$TODO"
+	case "$command" in
+	\#|'')
+		mark_action_done
+		continue
+		;;
+	pick)
+		comment_for_reflog pick
+
+		mark_action_done
+		pick_one $sha1 ||
+			die_with_patch $sha1 "Could not apply $sha1... $rest"
+		;;
+	edit)
+		comment_for_reflog edit
+
+		mark_action_done
+		pick_one $sha1 ||
+			die_with_patch $sha1 "Could not apply $sha1... $rest"
+		make_patch $sha1
+		warn
+		warn "You can amend the commit now, with"
+		warn
+		warn "	git commit --amend"
+		warn
+		exit 0
+		;;
+	squash)
+		comment_for_reflog squash
+
+		test -z "$(grep -ve '^$' -e '^#' < $DONE)" &&
+			die "Cannot 'squash' without a previous commit"
+
+		mark_action_done
+		failed=f
+		pick_one -n $sha1 || failed=t
+		MSG="$DOTEST"/message
+		echo "# This is a combination of two commits." > "$MSG"
+		echo "# The first commit's message is:" >> "$MSG"
+		echo >> "$MSG"
+		git cat-file commit HEAD | sed -e '1,/^$/d' >> "$MSG"
+		echo >> "$MSG"
+		echo "# And this is the 2nd commit message:" >> "$MSG"
+		echo >> "$MSG"
+		git cat-file commit $sha1 | sed -e '1,/^$/d' >> "$MSG"
+		git reset --soft HEAD^
+		author_script=$(get_author_ident_from_commit $sha1)
+		case $failed in
+		f)
+			# This is like --amend, but with a different message
+			eval "$author_script"
+			export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
+			git commit -F "$MSG" -e
+			;;
+		t)
+			cp "$MSG" "$GIT_DIR"/MERGE_MSG
+			warn
+			warn "Could not apply $sha1... $rest"
+			warn "After you fixed that, commit the result with"
+			warn
+			warn "  $(echo $author_script | tr '\012' ' ') \\"
+			warn "	  git commit -F \"$GIT_DIR\"/MERGE_MSG -e"
+			die_with_patch $sha1 ""
+		esac
+		;;
+	*)
+		warn "Unknown command: $command $sha1 $rest"
+		die_with_patch $sha1 "Please fix this in the file $TODO."
+	esac
+	test -s "$TODO" && return
+
+	HEAD=$(git rev-parse HEAD)
+	HEADNAME=$(cat "$DOTEST"/head-name)
+	rm -rf "$DOTEST" &&
+	warn "Successfully rebased and updated $HEADNAME."
+
+	exit
+}
+
+do_rest () {
+	while :
+	do
+		do_next
+	done
+	test -f "$DOTEST"/verbose &&
+		git diff --stat $(cat "$DOTEST"/head)..HEAD
+	exit
+}
+
+while case $# in 0) break ;; esac
+do
+	case "$1" in
+	--continue)
+		comment_for_reflog continue
+
+		test -d "$DOTEST" || die "No interactive rebase running"
+
+		require_clean_work_tree
+		do_rest
+		;;
+	--abort)
+		comment_for_reflog abort
+
+		test -d "$DOTEST" || die "No interactive rebase running"
+
+		HEADNAME=$(cat "$DOTEST"/head-name)
+		HEAD=$(cat "$DOTEST"/head)
+		git symbolic-ref HEAD $HEADNAME &&
+		git reset --hard $HEAD &&
+		rm -rf "$DOTEST"
+		exit
+		;;
+	--skip)
+		comment_for_reflog skip
+
+		test -d "$DOTEST" || die "No interactive rebase running"
+
+		git reset --hard && do_rest
+		;;
+	-s|--strategy)
+		shift
+		case "$#,$1" in
+		*,*=*)
+			STRATEGY="-s `expr "z$1" : 'z-[^=]*=\(.*\)'`" ;;
+		1,*)
+			usage ;;
+		*)
+			STRATEGY="-s $2"
+			shift ;;
+		esac
+		;;
+	--merge)
+		# we use merge anyway
+		;;
+	-C*)
+		die "Interactive rebase uses merge, so $1 does not make sense"
+		;;
+	-v)
+		VERBOSE=t
+		;;
+	-i|--interactive)
+		# yeah, we know
+		;;
+	''|-h)
+		usage
+		;;
+	*)
+		test -d "$DOTEST" &&
+			die "Interactive rebase already started"
+
+		git var GIT_COMMITTER_IDENT >/dev/null ||
+			die "You need to set your committer info first"
+
+		comment_for_reflog start
+
+		ONTO=
+		case "$1" in
+		--onto)
+			ONTO=$(git rev-parse --verify "$2") ||
+				die "Does not point to a valid commit: $2"
+			shift; shift
+			;;
+		esac
+
+		require_clean_work_tree
+
+		if [ ! -z "$2"]
+		then
+			git show-ref --verify --quiet "refs/heads/$2" ||
+				die "Invalid branchname: $2"
+			git checkout "$2" ||
+				die "Could not checkout $2"
+		fi
+
+		HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
+		UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
+
+		test -z "$ONTO" && ONTO=$UPSTREAM
+
+		mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
+		: > "$DOTEST"/interactive || die "Could not mark as interactive"
+		git symbolic-ref HEAD > "$DOTEST"/head-name ||
+			die "Could not get HEAD"
+
+		echo $HEAD > "$DOTEST"/head
+		echo $UPSTREAM > "$DOTEST"/upstream
+		echo $ONTO > "$DOTEST"/onto
+		test t = "$VERBOSE" && : > "$DOTEST"/verbose
+
+		cat > "$TODO" << EOF
+# Rebasing $UPSTREAM..$HEAD onto $ONTO
+#
+# Commands:
+#  pick = use commit
+#  edit = use commit, but stop for amending
+#  squash = use commit, but meld into previous commit
+EOF
+		git rev-list --no-merges --pretty=oneline --abbrev-commit \
+			--abbrev=7 --reverse $UPSTREAM..$HEAD | \
+			sed "s/^/pick /" >> "$TODO"
+
+		test -z "$(grep -ve '^$' -e '^#' < $TODO)" &&
+			die "Nothing to do"
+
+		cp "$TODO" "$TODO".backup
+		${VISUAL:-${EDITOR:-vi}} "$TODO" ||
+			die "Could not execute editor"
+
+		git reset --hard $ONTO && do_rest
+	esac
+	shift
+done
diff --git a/git-rebase.sh b/git-rebase.sh
index 2aa3a01..3887526 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano.
 #
 
-USAGE='[-v] [--onto <newbase>] <upstream> [<branch>]'
+USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
 same name.  When the --onto option is provided the new branch starts
 out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
@@ -120,6 +120,16 @@ finish_rb_merge () {
 	echo "All done."
 }
 
+is_interactive () {
+	test -f "$dotest"/interactive ||
+	while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
+	do
+		shift
+	done && test -n "$1"
+}
+
+is_interactive "$@" && exec git-rebase--interactive "$@"
+
 while case "$#" in 0) break ;; esac
 do
 	case "$1" in
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
new file mode 100755
index 0000000..48aa8ea
--- /dev/null
+++ b/t/t3404-rebase-interactive.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='git rebase interactive
+
+This test runs git rebase "interactively", by faking an edit, and verifies
+that the result still makes sense.
+'
+. ./test-lib.sh
+
+# set up two branches like this:
+#
+# A - B - C - D - E
+#   \
+#     F - G - H
+#       \
+#         I
+#
+# where B, D and G touch the same file.
+
+test_expect_success 'setup' '
+	: > file1 &&
+	git add file1 &&
+	test_tick &&
+	git commit -m A &&
+	git tag A &&
+	echo 1 > file1 &&
+	test_tick &&
+	git commit -m B file1 &&
+	: > file2 &&
+	git add file2 &&
+	test_tick &&
+	git commit -m C &&
+	echo 2 > file1 &&
+	test_tick &&
+	git commit -m D file1 &&
+	: > file3 &&
+	git add file3 &&
+	test_tick &&
+	git commit -m E &&
+	git checkout -b branch1 A &&
+	: > file4 &&
+	git add file4 &&
+	test_tick &&
+	git commit -m F &&
+	git tag F &&
+	echo 3 > file1 &&
+	test_tick &&
+	git commit -m G file1 &&
+	: > file5 &&
+	git add file5 &&
+	test_tick &&
+	git commit -m H &&
+	git checkout -b branch2 F &&
+	: > file6 &&
+	git add file6 &&
+	test_tick &&
+	git commit -m I &&
+	git tag I
+'
+
+cat > fake-editor.sh << EOF
+#!/bin/sh
+test "\$1" = .git/COMMIT_EDITMSG && exit
+test -z "\$FAKE_LINES" && exit
+grep -v "^#" < "\$1" > "\$1".tmp
+rm "\$1"
+cat "\$1".tmp
+action=pick
+for line in \$FAKE_LINES; do
+	case \$line in
+	squash)
+		action="\$line";;
+	*)
+		echo sed -n "\${line}s/^pick/\$action/p"
+		sed -n "\${line}p" < "\$1".tmp
+		sed -n "\${line}s/^pick/\$action/p" < "\$1".tmp >> "\$1"
+		action=pick;;
+	esac
+done
+EOF
+
+chmod a+x fake-editor.sh
+VISUAL="$(pwd)/fake-editor.sh"
+export VISUAL
+
+test_expect_success 'no changes are a nop' '
+	git rebase -i F &&
+	test $(git rev-parse I) = $(git rev-parse HEAD)
+'
+
+test_expect_success 'rebase on top of a non-conflicting commit' '
+	git checkout branch1 &&
+	git tag original-branch1 &&
+	git rebase -i branch2 &&
+	test file6 = $(git diff --name-only original-branch1) &&
+	test $(git rev-parse I) = $(git rev-parse HEAD~2)
+'
+
+test_expect_success 'exchange two commits' '
+	FAKE_LINES="2 1" git rebase -i HEAD~2 &&
+	test H = $(git cat-file commit HEAD^ | tail -n 1) &&
+	test G = $(git cat-file commit HEAD | tail -n 1)
+'
+
+cat > expect << EOF
+diff --git a/file1 b/file1
+index e69de29..00750ed 100644
+--- a/file1
++++ b/file1
+@@ -0,0 +1 @@
++3
+EOF
+
+cat > expect2 << EOF
+<<<<<<< HEAD:file1
+2
+=======
+3
+>>>>>>> b7ca976... G:file1
+EOF
+
+test_expect_success 'stop on conflicting pick' '
+	git tag new-branch1 &&
+	! git rebase -i master &&
+	diff -u expect .git/.dotest-merge/patch &&
+	diff -u expect2 file1 &&
+	test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) &&
+	test 0 = $(grep -v "^#" < .git/.dotest-merge/todo | wc -l)
+'
+
+test_expect_success 'abort' '
+	git rebase --abort &&
+	test $(git rev-parse new-branch1) = $(git rev-parse HEAD) &&
+	! test -d .git/.dotest-merge
+'
+
+test_expect_success 'retain authorship' '
+	echo A > file7 &&
+	git add file7 &&
+	GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" &&
+	git tag twerp &&
+	git rebase -i --onto master HEAD^ &&
+	git show HEAD | grep "^Author: Twerp Snog"
+'
+
+test_expect_success 'squash' '
+	git reset --hard twerp &&
+	echo B > file7 &&
+	GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 &&
+	echo "******************************" &&
+	FAKE_LINES="1 squash 2" git rebase -i --onto master HEAD~2 &&
+	test B = $(cat file7) &&
+	test $(git rev-parse HEAD^) = $(git rev-parse master)
+'
+
+test_expect_success 'retain authorship when squashing' '
+	git show HEAD | grep "^Author: Nitfol"
+'
+
+test_done
-- 
1.5.2.2.279.g9b198-dirty

^ permalink raw reply related

* [PATCH] Add core.quotepath configuration variable.
From: Junio C Hamano @ 2007-06-25  0:11 UTC (permalink / raw)
  To: git

We always quote "unusual" byte values in a pathname using
C-string style, to make it safer for parsing scripts that do not
handle NUL separated records well (or just too lazy to bother).
The absolute minimum bytes that need to be quoted for this
purpose are TAB, LF (and other control characters), double quote
and backslash.

However, we have also always quoted the bytes in high 8-bit
range; this was partly because we were lazy and partly because
we were being cautious.

This introduces an internal "quote_path_fully" variable, and
core.quotepath configuration variable to control it.  When set
to false, it does not quote bytes in high 8-bit range anymore
but passes them intact.

The variable defaults to "true" to retain the traditional
behaviour for now.  Maybe in later versions of git we might want
to change the default to false, so people need to explicitly ask
for safer quoting.  But that would be for a separate patch in
different timeframe.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt |   12 ++++
 cache.h                  |    1 +
 config.c                 |    5 ++
 environment.c            |    1 +
 quote.c                  |    5 +-
 t/t3902-quoted.sh        |  126 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 148 insertions(+), 2 deletions(-)
 create mode 100755 t/t3902-quoted.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index a2057d9..34b1c97 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -117,6 +117,18 @@ core.fileMode::
 	the working copy are ignored; useful on broken filesystems like FAT.
 	See gitlink:git-update-index[1]. True by default.
 
+core.quotepath::
+	The commands that output paths (e.g. `ls-files`,
+	`diff`), when not given the `-z` option, will quote
+	"unusual" characters in the pathname by enclosing the
+	pathname in a double-quote pair and with backslashes the
+	same way strings in C source code are quoted.  If this
+	variable is set to false, the bytes higher than 0x80 are
+	not quoted but output as verbatim.  Note that double
+	quote, backslash and control characters are always
+	quoted without `-z` regardless of the setting of this
+	variable.
+
 core.autocrlf::
 	If true, makes git convert `CRLF` at the end of lines in text files to
 	`LF` when reading from the filesystem, and convert in reverse when
diff --git a/cache.h b/cache.h
index ed83d92..6776357 100644
--- a/cache.h
+++ b/cache.h
@@ -292,6 +292,7 @@ extern int delete_ref(const char *, const unsigned char *sha1);
 
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
+extern int quote_path_fully;
 extern int has_symlinks;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
diff --git a/config.c b/config.c
index e323153..4de8926 100644
--- a/config.c
+++ b/config.c
@@ -271,6 +271,11 @@ int git_default_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.quotepath")) {
+		quote_path_fully = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "core.symlinks")) {
 		has_symlinks = git_config_bool(var, value);
 		return 0;
diff --git a/environment.c b/environment.c
index 8b9b89d..1c2773f 100644
--- a/environment.c
+++ b/environment.c
@@ -12,6 +12,7 @@
 char git_default_email[MAX_GITNAME];
 char git_default_name[MAX_GITNAME];
 int trust_executable_bit = 1;
+int quote_path_fully = 1;
 int has_symlinks = 1;
 int assume_unchanged;
 int prefer_symlink_refs;
diff --git a/quote.c b/quote.c
index aa44009..d88bf75 100644
--- a/quote.c
+++ b/quote.c
@@ -188,7 +188,8 @@ static int quote_c_style_counted(const char *name, int namelen,
 #define EMITQ() EMIT('\\')
 
 	const char *sp;
-	int ch, count = 0, needquote = 0;
+	unsigned char ch;
+	int count = 0, needquote = 0;
 
 	if (!no_dq)
 		EMIT('"');
@@ -197,7 +198,7 @@ static int quote_c_style_counted(const char *name, int namelen,
 		if (!ch)
 			break;
 		if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
-		    (ch >= 0177)) {
+		    (quote_path_fully && (ch >= 0177))) {
 			needquote = 1;
 			switch (ch) {
 			case '\a': EMITQ(); ch = 'a'; break;
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
new file mode 100755
index 0000000..63f950b
--- /dev/null
+++ b/t/t3902-quoted.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Junio C Hamano
+#
+
+test_description='quoted output'
+
+. ./test-lib.sh
+
+FN='濱野'
+GN='純'
+HT='	'
+LF='
+'
+DQ='"'
+
+for_each_name () {
+	for name in \
+	    Name "Name and a${LF}LF" "Name and an${HT}HT" "Name${DQ}" \
+	    "$FN$HT$GN" "$FN$LF$GN" "$FN $GN" "$FN$GN" "$FN$DQ$GN" \
+	    "With SP in it"
+	do
+		eval "$1"
+	done
+}
+
+test_expect_success setup '
+
+	for_each_name "echo initial >\"\$name\""
+	git add . &&
+	git commit -q -m Initial &&
+
+	for_each_name "echo second >\"\$name\"" &&
+	git commit -a -m Second
+
+	for_each_name "echo modified >\"\$name\""
+
+'
+
+cat >expect.quoted <<\EOF
+Name
+"Name and a\nLF"
+"Name and an\tHT"
+"Name\""
+With SP in it
+"\346\277\261\351\207\216\t\347\264\224"
+"\346\277\261\351\207\216\n\347\264\224"
+"\346\277\261\351\207\216 \347\264\224"
+"\346\277\261\351\207\216\"\347\264\224"
+"\346\277\261\351\207\216\347\264\224"
+EOF
+
+cat >expect.raw <<\EOF
+Name
+"Name and a\nLF"
+"Name and an\tHT"
+"Name\""
+With SP in it
+"濱野\t純"
+"濱野\n純"
+濱野 純
+"濱野\"純"
+濱野純
+EOF
+
+test_expect_success 'check fully quoted output from ls-files' '
+
+	git ls-files >current && diff -u expect.quoted current
+
+'
+
+test_expect_success 'check fully quoted output from diff-files' '
+
+	git diff --name-only >current &&
+	diff -u expect.quoted current
+
+'
+
+test_expect_success 'check fully quoted output from diff-index' '
+
+	git diff --name-only HEAD >current &&
+	diff -u expect.quoted current
+
+'
+
+test_expect_success 'check fully quoted output from diff-tree' '
+
+	git diff --name-only HEAD^ HEAD >current &&
+	diff -u expect.quoted current
+
+'
+
+test_expect_success 'setting core.quotepath' '
+
+	git config --bool core.quotepath false
+
+'
+
+test_expect_success 'check fully quoted output from ls-files' '
+
+	git ls-files >current && diff -u expect.raw current
+
+'
+
+test_expect_success 'check fully quoted output from diff-files' '
+
+	git diff --name-only >current &&
+	diff -u expect.raw current
+
+'
+
+test_expect_success 'check fully quoted output from diff-index' '
+
+	git diff --name-only HEAD >current &&
+	diff -u expect.raw current
+
+'
+
+test_expect_success 'check fully quoted output from diff-tree' '
+
+	git diff --name-only HEAD^ HEAD >current &&
+	diff -u expect.raw current
+
+'
+
+test_done
-- 
1.5.2.2.1334.g1625

^ permalink raw reply related

* Re: DWIM ref names for push/fetch
From: Junio C Hamano @ 2007-06-25  0:09 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706241808550.4740@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> Is this difference simply due to the different languages the matching 
> portions of these were originally written in?

If anything, the semantics on the fetch side is _very_ much
intentional and is done deliberately that way to be usable.  

On the other hand, push started as "matching only", and then
"match tail part of the name" as an afterthought.  It was so
afterthought that it had an idiotic behaviour of independently
match the source and destination side even when there is no
colon, which was fixed only recently.

So if you would want to match fetch and push, you should not
change the semantics on fetch to match what push does, as the
latter was done pretty much without design.

Having said that, I think fetch and push DWIMmery are
fundamentally different, especially when you do not have a
colon.  push without storing anything on the receiving end would
not make any sense whatsoever, but fetch without using tracking
branches does make perfect sense, so push does pretend dst side
has what matched with src side pattern, while fetch treats no
colon pattern as not storing.  IOW, even if we wanted to reuse
the code on both sides as much as possible, I suspect we would
need to have details different between them.

^ permalink raw reply

* [PATCH 1/2] Move the pick_author code to git-sh-setup
From: Johannes Schindelin @ 2007-06-25  0:04 UTC (permalink / raw)
  To: Junio C Hamano, Brian Gernhardt; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706241204450.4059@racer.site>


At the moment, only git-commit uses that code, to pick the author name,
email and date from a given commit.

This code will be reused in git rebase --interactive.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	Just the eval was changed, by dq'ing its argument.

 git-commit.sh   |   30 ++----------------------------
 git-sh-setup.sh |   27 +++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/git-commit.sh b/git-commit.sh
index 5547a02..d43bdd8 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -483,34 +483,8 @@ fi >>"$GIT_DIR"/COMMIT_EDITMSG
 # Author
 if test '' != "$use_commit"
 then
-	pick_author_script='
-	/^author /{
-		s/'\''/'\''\\'\'\''/g
-		h
-		s/^author \([^<]*\) <[^>]*> .*$/\1/
-		s/'\''/'\''\'\'\''/g
-		s/.*/GIT_AUTHOR_NAME='\''&'\''/p
-
-		g
-		s/^author [^<]* <\([^>]*\)> .*$/\1/
-		s/'\''/'\''\'\'\''/g
-		s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
-
-		g
-		s/^author [^<]* <[^>]*> \(.*\)$/\1/
-		s/'\''/'\''\'\'\''/g
-		s/.*/GIT_AUTHOR_DATE='\''&'\''/p
-
-		q
-	}
-	'
-	encoding=$(git config i18n.commitencoding || echo UTF-8)
-	set_author_env=`git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
-	LANG=C LC_ALL=C sed -ne "$pick_author_script"`
-	eval "$set_author_env"
-	export GIT_AUTHOR_NAME
-	export GIT_AUTHOR_EMAIL
-	export GIT_AUTHOR_DATE
+	eval "$(get_author_ident_from_commit "$use_commit")"
+	export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
 fi
 if test '' != "$force_author"
 then
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index f24c7f2..d861db3 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -53,6 +53,33 @@ require_work_tree () {
 	die "fatal: $0 cannot be used without a working tree."
 }
 
+get_author_ident_from_commit () {
+	pick_author_script='
+	/^author /{
+		s/'\''/'\''\\'\'\''/g
+		h
+		s/^author \([^<]*\) <[^>]*> .*$/\1/
+		s/'\''/'\''\'\'\''/g
+		s/.*/GIT_AUTHOR_NAME='\''&'\''/p
+
+		g
+		s/^author [^<]* <\([^>]*\)> .*$/\1/
+		s/'\''/'\''\'\'\''/g
+		s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
+
+		g
+		s/^author [^<]* <[^>]*> \(.*\)$/\1/
+		s/'\''/'\''\'\'\''/g
+		s/.*/GIT_AUTHOR_DATE='\''&'\''/p
+
+		q
+	}
+	'
+	encoding=$(git config i18n.commitencoding || echo UTF-8)
+	git show -s --pretty=raw --encoding="$encoding" "$1" |
+	LANG=C LC_ALL=C sed -ne "$pick_author_script"
+}
+
 if [ -z "$LONG_USAGE" ]
 then
 	LONG_USAGE="Usage: $0 $USAGE"
-- 
1.5.2.2.279.g9b198-dirty

^ permalink raw reply related

* Re: Darcs
From: Linus Torvalds @ 2007-06-25  0:00 UTC (permalink / raw)
  To: Dan Chokola; +Cc: Junio C Hamano, Martin Langhoff, Bu Bacoo, git
In-Reply-To: <61e816970706241638j60830741p2cd1a102a72ae226@mail.gmail.com>



On Sun, 24 Jun 2007, Dan Chokola wrote:
> 
> What I have noticed is a lot of nitpicking, of which I'm guilty, too. The
> issue Linus brought up about Darcs and versioning is not one I typically see
> surface in real life. Users usually complain about some _release_ version
> or, "I updated last week."

Actually, in the kernel, we are getting quite a lot out of "git bisect", 
and people throw git SHA1's around to describe where they are, or a 
particular commit.

Which never happened with BK.

So I think that the _ability_ to name revisions easily across different 
uses is quite important, because it then drives behaviour.

Without it, you'll never notice you need it. With it, you start wondering 
how others handle it.

For example, we have people like Andrew, who don't really "use" git, and 
he starts pointing to commits with their git ID, because he sees them 
flying past, and he knows they are stable and useful for things like 
gitweb.

			Linus

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox