Git development
 help / color / mirror / Atom feed
* Re: [PATCH/RFC] "init-db" can really be just "init"
From: Johannes Schindelin @ 2006-11-27 23:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Pitre, git
In-Reply-To: <7vmz6cfsuw.fsf@assigned-by-dhcp.cox.net>

Hi,

On Mon, 27 Nov 2006, Junio C Hamano wrote:

> Nicolas Pitre <nico@cam.org> writes:
> 
> > Maybe that could be a good rule of thumb to have all porcelainish 
> > commands not have any hyphen in their name, like "diff", "commit", 
> > "add", etc. ?
> 
> I was also hoping that would become the case except verify-tag,
> cherry-pick, and format-patch.

I agree it might make a good rule-of-thumb, but let's not be overzealous. 
I have yet to see any better names for those three either, let alone 
better names without a hyphen.

> Also I was wondering if it would make sense to give two dashes to the 
> back-end ones that never get invoked by the end users directly (e.g. 
> merge--recursive, upload--pack) but thought it was too ugly.

I think it would appeal mostly to our friends, the monotone users...

Ciao,
Dscho

^ permalink raw reply

* Re: Idea for rebase strategy
From: Johannes Schindelin @ 2006-11-27 23:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfyc5l24t.fsf@assigned-by-dhcp.cox.net>

Hi,

On Mon, 27 Nov 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > an idea hit me today: maybe we can make rebase work nicely with merges 
> > after all. We could record the original branch point and the new branch 
> > point for rebases.
> 
> [...]
> 
> If we have a reliable ref-log for 'topic' that should be trivial
> to do.

But of course! Yet another reason to introduce core.disableRefLog, and 
turn it on by default...

The graceful merging of a rebased branch indeed depends on the local 
history, i.e. what is stored in the reflog.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] (experimental) per-topic shortlog.
From: Johannes Schindelin @ 2006-11-27 23:46 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0611261652520.30076@woody.osdl.org>

Hi,

On Sun, 26 Nov 2006, Linus Torvalds wrote:

> Of course, such a thing done well would probably be worthy of a doctoral 
> thesis or something. Maybe somebody on this list who is into bayesian 
> clustering and doesn't have a thesis subject...

Funny you should mention it... I recently was exposed to Formal Concept 
Analysis, and immediately thought that this would have applications in the 
visualization of source codes' histories.

Maybe there is a way to apply Bayesian Inference to determine a subset 
which bears the highest information / subset size ratio.

As for reducing the number of lines in the shortlog: taking myself as an 
example, I often touch the same code several times, just to fix bugs. So, 
if the same code was touched several times, just take the first oneline, 
and add "(+fixes)". Of course, this is more like a wedding between 
shortlog and annotate, and likely to be slow.

Ciao,
Dscho

^ permalink raw reply

* Re: Hyphens and hiding core commands
From: Junio C Hamano @ 2006-11-27 23:59 UTC (permalink / raw)
  To: Carl Worth; +Cc: Nicolas Pitre, git
In-Reply-To: <87bqmswm1e.wl%cworth@cworth.org>

Carl Worth <cworth@cworth.org> writes:

> There's another rule-of-thumb I would like to propose that's a bit
> harder to state, but I think is just as important (if not more):
>
> 	For introductory documentation it should never make sense to
> 	introduce a command with specific command-line options before
> 	the same command without options.

I tend to disagree.  "This is the easiest way to use, even for
beginners" and "this way should be the default for all levels of
users" are quite different.

> As examples, both "commit -a" and "cat-file -p" fail that test and
> both appear in the git tutorial here:
>
> 	http://www.kernel.org/pub/software/scm/git/docs/tutorial.html
>
> My proposals to fix those two are:

Creating a "git cat" and promote that in the Tutorial makes a
lot of sense, but then that can easily be done with aliases ;-).
cat-file is plumbing.  We did not even have '-p' and you needed
to _know_ the type of stuff you are feeding and we had '-t' to
help you do so.  '-p' was done as a quick hack because showing
the representation of any object in semi human readable way was
not all that important but occasionally people found it useful,
and it just was an easy thing to do inside cat-file.  Nobody
bothered to do a real Porcelain called "git cat" for that
purpose, so far, but that is probably what should have been.  On
the other hand, if "cat-file -p" needs to be used often, I think
there is something ELSE that is wrong.

I do not think defaulting to "commit -a" is a fix; rather, it
feels exactly what Linus was talking about when he said about
"second system syndrome".

I would not mind if you created "commit-easy" (just like curl
library has curl_x_easy), but the current way the command works
is more useful once you grok the index.  Being able to work in a
slightly dirty tree and commit only the necessary things, and
being able to do so even for a merge commit, is damn convenient.

Because there is a learning curve involved, an easier way to use
git without worrying about the index was added in the form of
'-a' for beginners.  People who use index regularly should not
be forced to spend extra keystrokes for the rest of their lives
only because you want to lose '-a' from the tutorial document.
The tool should be designed for regular users, not for the first
few pages of the tutorial.

^ permalink raw reply

* Re: [PATCH] revision traversal: Add --refs=<pattern> option
From: Junio C Hamano @ 2006-11-27 23:59 UTC (permalink / raw)
  To: Sergey Vlasov; +Cc: git
In-Reply-To: <11646401513369-git-send-email-vsu@altlinux.ru>

Sergey Vlasov <vsu@altlinux.ru> writes:

> Add the --refs=<pattern> option, which can be used to select a
> subset of refs matching the specified glob pattern.
>
> Signed-off-by: Sergey Vlasov <vsu@altlinux.ru>
> ---
>
>  If --all-branches is too specific for the mentioned use case,
>  what about adding a more general glob pattern match?

Traditionally any new option to rev-list must be accompanied
with a matching change to rev-parse.  I do not know offhand how
strictly we should adhere to this rule these days; it depends on
how people's script use rev-list.

Before revision.c "revision walking library" was done, many
Porcelain-ish commands were implemented as a pipeline that plugs
rev-list output to diff-tree.  These shell scripts took
parameters from the command line, and rev-parse was used to
separate parameters (both "flags" that begin with a dash and
"non-flags" that don't) that should be given to rev-list and the
other parameters (meant to be used by the shell script itself
but often are given straight to the downstream diff-tree).  The
rev-parse command has even the --sq option to facilitate this
usage:

	rev_opts=`git rev-parse --sq --default=HEAD --revs "$@"`
	diff_opts=`git rev-parse --sq --no-revs "$@"`
        eval "git-rev-list $rev_opts" |
        eval "git-diff-tree --stdin $diff_opts"

so that it can even pass -S'I want to find this string' to diff-tree
without worrying about spaces.

I personally feel that part of rev-parse outlived its usefulness
(--flags, --no-flags, --revs-only, and --no-revs).  It was a
useful hack, and served us well, but it was a hack.

In that sense it probably is Ok to leave it unmaintained, but it
might be a good idea to plan deprecating it, given that we have
been talking about UI warts.  If there are pipelines that can be
easily formed (with the help of rev-parse "parameter sifter"),
but whose functionality cannot be easily emulated with the
current crop of Porcelain-ish, we should work on polishing the
Porcelain-ish to make the pipelines unnecessary.

The remaining parts of rev-parse (the most important of which is
the --verify option) should probably stay.  The original
question of "list all the branches" can be done with:

	git rev-parse --symbolic --branches


^ permalink raw reply

* git and bzr
From: Joseph Wakeling @ 2006-11-28  0:01 UTC (permalink / raw)
  To: git; +Cc: bazaar-ng
In-Reply-To: <Pine.LNX.4.64.0610260753090.3962@g5.osdl.org>

Hello all,

Following the very interesting debate about the differences between bzr
and git, I thought it was about time I tried to learn properly about git
and how to use it.  I've been using bzr for a good while now, although
since I'm not a serious developer I only use it for simple purposes,
keeping track of code I write on my own for academic projects.

So, a few questions about differences I don't understand...

First off a really dumb one: how do I identify myself to git, i.e. give
it a name and email address?  Currently it uses my system identity,
My Name <username@computer.(none)>.  I haven't found any equivalent of
the bzr whoami command.

Now to more serious business.  One of the main operational differences I
see as a new user is that bzr defaults to setting up branches in
different locations, whereas git by default creates a repository where
branches are different versions of the directory contents and switching
branches *changes* the directory contents.  bzr branch seems to be
closer to git-clone than git-branch (N.B. I have never used bzr repos so
might not be making a fair comparison).

With this in mind, is there any significance to the "master" branch (is
it intended e.g. to indicate a git repository's "stable" version
according to the owner?), or is this just a convenient default name?
Could I delete or rename it?  Using bzr I would normally give the
central branch(*) the name of the project.

(* Central or main on my own system.  Not intended to be central in the
sense of a CVS-style version control setup:-)

Any other useful comments that can be made to a bzr user about working
with this difference, positive or negative aspects of it?

Next question ... one of the reasons I started seriously thinking about
git was that in the VCS comparison discussion, it was noted that git is
a lot more flexible than bzr in terms of how it can track data (e.g. the
git pickaxe command, although I understand that's not in the released
version [1.4.4.1] yet?).  A frustration with bzr is that pulling or
merging patches from another branch or repo requires them to share the
same HEAD.  Is this a requirement in git or can I say, "Hey, I like that
particular function in project XXX, I'm going to pull that individual
bit of code and its development history into project YYY"?

Last off (for now, I'm sure I'll think of more): is there any easy (or
difficult) way to effectively import version history from a bzr
repository, and vice versa?

Thanks in advance for any comments,

    -- Joe

^ permalink raw reply

* Re: [PATCH] (experimental) per-topic shortlog.
From: Junio C Hamano @ 2006-11-28  0:09 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, Linus Torvalds
In-Reply-To: <Pine.LNX.4.63.0611280040480.30004@wbgn013.biozentrum.uni-wuerzburg.de>

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

> As for reducing the number of lines in the shortlog: taking myself as an 
> example, I often touch the same code several times, just to fix bugs. So, 
> if the same code was touched several times, just take the first oneline, 
> and add "(+fixes)". Of course, this is more like a wedding between 
> shortlog and annotate, and likely to be slow.

Interesting.  While driving to work this morning I had the same
thought.  A revision that does not appear in the output from

	for file in $(list of files the commit touches)
        do
		git blame v2.6.17..v2.6.18 -- $file
	done

can safely be omitted from the shortlog, because later changes
fully supersedes it.

I think the list of "important" changes is an interesting
problem, but the importance may not directly be related to the
number of paths a patch touches (e.g. "you reorder the members
of a structure everybody uses in one include file and everything
starts performing faster due to better cache behaviour" would be
a few lines of a single header file).  Also better clues to
judge the importance would be found outside the repository.
"The patch discussed by many people on the list" and "the patch
that had very many iteration to get in the final shape" would
certainly be interesting ones, but that information is often not
found in the repository.


^ permalink raw reply

* Re: SEGV when lookup_* returns NULL
From: Junio C Hamano @ 2006-11-28  0:13 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Martin Waitz, git
In-Reply-To: <Pine.LNX.4.63.0611280032300.30004@wbgn013.biozentrum.uni-wuerzburg.de>

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

> And it would totally clobber the long term goal of libifying git.

Why?  You would certainly install your own die() handler by that
time I presume?

^ permalink raw reply

* Re: Hyphens and hiding core commands
From: Carl Worth @ 2006-11-28  0:23 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Pitre, git
In-Reply-To: <7vodqse90q.fsf@assigned-by-dhcp.cox.net>

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

On Mon, 27 Nov 2006 15:59:17 -0800, Junio C Hamano wrote:
>
> I tend to disagree.  "This is the easiest way to use, even for
> beginners" and "this way should be the default for all levels of
> users" are quite different.

I'll gladly agree that different defaults make sense for different
users. Fortunately, we have a config file syntax that allows advanced
users to select the defaults they prefer. But, what should be obvious
is that the config file is not an option available for reducing the
learning curve of git.

> Creating a "git cat" and promote that in the Tutorial makes a
> lot of sense, but then that can easily be done with aliases ;-).
...
> On the other hand, if "cat-file -p" needs to be used often, I think
> there is something ELSE that is wrong.

Sure. I don't think "cat-file -p" is any big problem. I only mention
it because it _is_ mentioned in the git tutorial. So, let's add "git
cat" or else find some other way to address what the tutorial is
trying to demonstrate there.

> I would not mind if you created "commit-easy" (just like curl
> library has curl_x_easy),

Are you really serious about that? I think that's an awful idea.

Interfaces that give longer names to the simpler functionality are
really broken. There are plenty of examples of this kind of thing,
(XCreateWindow and XCreateSimpleWindow), but their existence in no way
justifies this as a good thing.

The git commit syntax already suffers from this, ("commit -a" being a
longer name than its conceptually more complex cousin, "commit"), so
"commit-easy" would only make that problem worse.

>                           but the current way the command works
> is more useful once you grok the index.  Being able to work in a
> slightly dirty tree and commit only the necessary things, and
> being able to do so even for a merge commit, is damn convenient.

Sure. You don't need to convert me to that idea. I use that mode
regularly, (though probably not more often than when committing an
index that happens to match my working tree). But my proposal doesn't
remove this functionality at all.

> Because there is a learning curve involved, an easier way to use
> git without worrying about the index was added in the form of
> '-a' for beginners.

Yes, there is a learning curve. There's the "once you grok the index"
stuff you just mentioned. And it's really backwards to have to teach
people that the "basic" way to do something is with a command line
that looks more complex, ("commit -a"), and that "once you learn more
you'll understand what that -a is all about and you'll know when not
to use it".

I've taught lots of people how to use git like that, and it's really
awkward. It would be much easier if learning new concepts and learning
new command-line options were correlated. That would allow whole
concepts to be dropped from the most basic introductions to git.

>                      People who use index regularly should not
> be forced to spend extra keystrokes for the rest of their lives
> only because you want to lose '-a' from the tutorial document.

You said yourself in the "cat-file -p" case, that can be done with
aliases. No extra keystrokes are needed.

And many potential users who are evaluating git compared to other
systems _do_ currently see something that will cost them extra
keystrokes for the rest of their lives. And that is being used as part
of the argument against git in some cases.

Now, maybe that's not the real reason people are rejecting git, but it
sure would be a nice excuse to remove from the potential list of
objections.

> The tool should be designed for regular users, not for the first
> few pages of the tutorial.

I'm not proposing eliminating the index or anything here. I really
don't see how the default of this one command has any impact at all on
the design of git. It's all still there.

-Carl

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: Mozilla, git and Windows
From: Sam Vilain @ 2006-11-28  0:30 UTC (permalink / raw)
  To: Jon Smirl; +Cc: Git Mailing List
In-Reply-To: <9e4733910611270728p36e58e08w6cc7a2989b7843ce@mail.gmail.com>

Jon Smirl wrote:
> In the other thread we are discussing the conversion of Mozilla CVS to
> git format. This is something that has to be done but it is not the
> only issue. Without a native Windows port they won't even consider
> using git. There is also the risk that the features needed by Mozilla
> will be completed after they choose to use a different SCM.
>
> Even if we implement all of the needed features git still needs to win
> the competition against the other possible choices. The last I heard
> the leading candiate is SVN/SVK.

Jon,

When I met clkao in August to discuss the possibility of using git as a
depot for SVK, he seemed very open to the idea, and we worked on an
initial plan for this.  This should eventually allow svk to be used as a
porcelain, which might make it more palatable to the Windows crowd.

However that doesn't solve the Windows porting issue - it would still
need to access the repository.

I've been working on and off on an abstraction to git, in Moose (perl 6
objects on perl 5) - what's working so far is making core objects, and
producing correct checksums.

You can see this early implementation at
http://utsl.gen.nz/gitweb/?p=VCS-Git

What I've found is that I need a good abstraction of UNIX pipelines that
is as portable as Perl, so that I can prototype the code basing it on
setting up command pipelines on UNIX, and have it gracefully degrade to
either using temporary files on Windows, or threading if portions are
re-implemented using Perl (or a ported libgit).  I am currently working
on this and hope to have a release by the end of the week, though I will
not have tested the Windows portability by then.

I would love it if anyone interested in the project would like to help
me complete the OO-based API, provide tests, documentation, or any kind
of feedback really.


^ permalink raw reply

* Re: git and bzr
From: Jakub Narebski @ 2006-11-28  0:39 UTC (permalink / raw)
  To: git; +Cc: bazaar-ng
In-Reply-To: <456B7C6A.80104@webdrake.net>

Joseph Wakeling wrote:

> Hello all,
> 
> Following the very interesting debate about the differences between bzr
> and git, I thought it was about time I tried to learn properly about git
> and how to use it.  I've been using bzr for a good while now, although
> since I'm not a serious developer I only use it for simple purposes,
> keeping track of code I write on my own for academic projects.
> 
> So, a few questions about differences I don't understand...
> 
> First off a really dumb one: how do I identify myself to git, i.e. give
> it a name and email address?  Currently it uses my system identity,
> My Name <username@computer.(none)>.  I haven't found any equivalent of
> the bzr whoami command.

git repo-config user.name "Joseph Wakeling"
git repo-config user.email joseph.wakeling@webdrake.net

You might add --global option if you want your identity to be saved
in ~/.gitconfig file, and not per repository (one might want to use
different identities for different repositories).

"git repo-config --list" or "git var -l" to list all config. There is no
direct equivalent of "bzr whoami" (the equivalent would be:

  echo "$(git repo-config --get user.name) <$(git repo-config --get user.email)>"
 
> Now to more serious business.  One of the main operational differences I
> see as a new user is that bzr defaults to setting up branches in
> different locations, whereas git by default creates a repository where
> branches are different versions of the directory contents and switching
> branches *changes* the directory contents.  bzr branch seems to be
> closer to git-clone than git-branch (N.B. I have never used bzr repos so
> might not be making a fair comparison).

The rough equivalent of bzr repos would be a set of git repos which share
object database, either via symlink, or via GIT_OBJECT_DIRECTORY, or via
alternates mechanism.

But it is a fact that in bzr working area is associated with branch, while
in git it is associated with repository.

> With this in mind, is there any significance to the "master" branch (is
> it intended e.g. to indicate a git repository's "stable" version
> according to the owner?), or is this just a convenient default name?
> Could I delete or rename it?  Using bzr I would normally give the
> central branch(*) the name of the project.

Of course you can rename 'master' branch. But please remember that names
of branches in git are local matter. Well, except the fact that you usually
preserve them in a fashion.

But equivalent of giving central branch the name of the project would
be naming the directory with working area and .git directory the name
of project, or in the case of bare repository giving $GIT_DIR for a project
name project.git.

> Any other useful comments that can be made to a bzr user about working
> with this difference, positive or negative aspects of it?

By the way, 'master' is by no means special. It is default in a few cases
(init-db, clone), but that's all.
 
> Next question ... one of the reasons I started seriously thinking about
> git was that in the VCS comparison discussion, it was noted that git is
> a lot more flexible than bzr in terms of how it can track data (e.g. the
> git pickaxe command, although I understand that's not in the released
> version [1.4.4.1] yet?).  A frustration with bzr is that pulling or
> merging patches from another branch or repo requires them to share the
> same HEAD.  Is this a requirement in git or can I say, "Hey, I like that
> particular function in project XXX, I'm going to pull that individual
> bit of code and its development history into project YYY"?

In git repository can have unrelated branches. So you can fetch unrelated
repository into your repository, and merge/cherry-pick from there
if needed.

In defence of Bazaar-NG, you can probably get the same or very similar with
bzr repos. 

> Last off (for now, I'm sure I'll think of more): is there any easy (or
> difficult) way to effectively import version history from a bzr
> repository, and vice versa?

Try git-archimport, or Tailor tool.
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git


^ permalink raw reply

* Re: git and bzr
From: Sean @ 2006-11-28  0:40 UTC (permalink / raw)
  To: Joseph Wakeling; +Cc: bazaar-ng, git
In-Reply-To: <456B7C6A.80104@webdrake.net>

On Tue, 28 Nov 2006 01:01:46 +0100
Joseph Wakeling <joseph.wakeling@webdrake.net> wrote:

> First off a really dumb one: how do I identify myself to git, i.e. give
> it a name and email address?  Currently it uses my system identity,
> My Name <username@computer.(none)>.  I haven't found any equivalent of
> the bzr whoami command.

Assuming you have a recent version of git, then:

$ git repo-config --global user.email "you@email.com"
$ git repo-config --global user.name "Your Name"

Will setup a ~/.gitconfig in your home directory; these settings
will apply in any repo you use.  Drop the "--global" to set them
per repo.

> With this in mind, is there any significance to the "master" branch (is
> it intended e.g. to indicate a git repository's "stable" version
> according to the owner?), or is this just a convenient default name?
> Could I delete or rename it?  Using bzr I would normally give the
> central branch(*) the name of the project.

It's just a common convention and carries no special significance;
rename away!

> Any other useful comments that can be made to a bzr user about working
> with this difference, positive or negative aspects of it?

Don't be afraid to git-clone your local repo, especially with the -l
and -s options.  That will get you a separate repo/working directory
while not taking up much extra disk space (objects from your first
repo will be shared with the second).

Once you get comfortable with multiple branches in a single repo/
working directory, it often is much better than the alternatives.
But the above gives you the option to work either way.

> Next question ... one of the reasons I started seriously thinking about
> git was that in the VCS comparison discussion, it was noted that git is
> a lot more flexible than bzr in terms of how it can track data (e.g. the
> git pickaxe command, although I understand that's not in the released
> version [1.4.4.1] yet?).  A frustration with bzr is that pulling or
> merging patches from another branch or repo requires them to share the
> same HEAD.  Is this a requirement in git or can I say, "Hey, I like that
> particular function in project XXX, I'm going to pull that individual
> bit of code and its development history into project YYY"?

The Git cherry-pick command lets you grab specific commits from
other branches in your repo.  But cherry-pick works at the commit
level, there is no easy way to grab a single function for instance
and merge just its history into another branch.

However, you can merge an entire separate project into yours even
though they don't share a base commit.  This has been done several
times in the history of Git itself. For instance you can see two
separate "initial" commits in the Git repo with a command like
"gitk README gitk" which gives a graphical history of the "gitk"
and "README" files and shows each started life in a separate
initial commit.  Use "git show 5569b" to see Linus bragging on
this first separate-project-merge and give some more details.
 
> Last off (for now, I'm sure I'll think of more): is there any easy (or
> difficult) way to effectively import version history from a bzr
> repository, and vice versa?

Don't think a direct bridge between the two has been written yet.

Cheers,
Sean




^ permalink raw reply

* Re: git and bzr
From: Sean @ 2006-11-28  0:40 UTC (permalink / raw)
  To: Joseph Wakeling; +Cc: git, bazaar-ng
In-Reply-To: <456B7C6A.80104@webdrake.net>

On Tue, 28 Nov 2006 01:01:46 +0100
Joseph Wakeling <joseph.wakeling@webdrake.net> wrote:

> First off a really dumb one: how do I identify myself to git, i.e. give
> it a name and email address?  Currently it uses my system identity,
> My Name <username@computer.(none)>.  I haven't found any equivalent of
> the bzr whoami command.

Assuming you have a recent version of git, then:

$ git repo-config --global user.email "you@email.com"
$ git repo-config --global user.name "Your Name"

Will setup a ~/.gitconfig in your home directory; these settings
will apply in any repo you use.  Drop the "--global" to set them
per repo.

> With this in mind, is there any significance to the "master" branch (is
> it intended e.g. to indicate a git repository's "stable" version
> according to the owner?), or is this just a convenient default name?
> Could I delete or rename it?  Using bzr I would normally give the
> central branch(*) the name of the project.

It's just a common convention and carries no special significance;
rename away!

> Any other useful comments that can be made to a bzr user about working
> with this difference, positive or negative aspects of it?

Don't be afraid to git-clone your local repo, especially with the -l
and -s options.  That will get you a separate repo/working directory
while not taking up much extra disk space (objects from your first
repo will be shared with the second).

Once you get comfortable with multiple branches in a single repo/
working directory, it often is much better than the alternatives.
But the above gives you the option to work either way.

> Next question ... one of the reasons I started seriously thinking about
> git was that in the VCS comparison discussion, it was noted that git is
> a lot more flexible than bzr in terms of how it can track data (e.g. the
> git pickaxe command, although I understand that's not in the released
> version [1.4.4.1] yet?).  A frustration with bzr is that pulling or
> merging patches from another branch or repo requires them to share the
> same HEAD.  Is this a requirement in git or can I say, "Hey, I like that
> particular function in project XXX, I'm going to pull that individual
> bit of code and its development history into project YYY"?

The Git cherry-pick command lets you grab specific commits from
other branches in your repo.  But cherry-pick works at the commit
level, there is no easy way to grab a single function for instance
and merge just its history into another branch.

However, you can merge an entire separate project into yours even
though they don't share a base commit.  This has been done several
times in the history of Git itself. For instance you can see two
separate "initial" commits in the Git repo with a command like
"gitk README gitk" which gives a graphical history of the "gitk"
and "README" files and shows each started life in a separate
initial commit.  Use "git show 5569b" to see Linus bragging on
this first separate-project-merge and give some more details.
 
> Last off (for now, I'm sure I'll think of more): is there any easy (or
> difficult) way to effectively import version history from a bzr
> repository, and vice versa?

Don't think a direct bridge between the two has been written yet.

Cheers,

^ permalink raw reply

* Re: Hyphens and hiding core commands
From: Junio C Hamano @ 2006-11-28  0:42 UTC (permalink / raw)
  To: Carl Worth; +Cc: git
In-Reply-To: <87ac2cwha4.wl%cworth@cworth.org>

Carl Worth <cworth@cworth.org> writes:

> Yes, there is a learning curve. There's the "once you grok the index"
> stuff you just mentioned. And it's really backwards to have to teach
> people that the "basic" way to do something is with a command line
> that looks more complex, ("commit -a"), and that "once you learn more
> you'll understand what that -a is all about and you'll know when not
> to use it".

I think you are teaching backwards.  Couldn't you start like this?

	"git commit" takes the list of paths you want to commit.
	Editing hello.c and saying "git commit hello.c" would
	commit your changes to hello.c.  It is cumbersome to
	list everything when your edit is all over the place,
	and in such a case you can say "git commit -a" to mean
	"everything I changed".

Later you can enhance that experience by teaching them index,
saying:

	You might want to tell git that your change to this file
	is more or less complete, even when you are not ready to
	commit the whole thing.  You could use update-index to
	mark them and then later say "git commit" will make a
	commit from the state you used update-index on, without
	having you list them on the command line.  When you do
	this, the commit template would list three classes of
	files and here are what they mean...



^ permalink raw reply

* Re: [PATCH] sha1_object_info(): be consistent with read_sha1_file()
From: Junio C Hamano @ 2006-11-28  1:05 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0611280016150.30004@wbgn013.biozentrum.uni-wuerzburg.de>

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

> We used to try loose objects first with sha1_object_info(), but packed
> objects first with read_sha1_file(). Now, prefer packed objects over loose
> ones with sha1_object_info(), too.

Well caught.  It appears this inconsistent order was from the
day one when we started using the packed git, and I forgot to
swap them when I did ab90ea5 to swap the reading side.

Thanks.



^ permalink raw reply

* Re: [PATCH 12/10] Teach bash about git-repo-config.
From: Junio C Hamano @ 2006-11-28  1:17 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20061127094447.GA19273@spearce.org>

"Shawn O. Pearce" <spearce@spearce.org> writes:

>  Yes, that's it.  I'm finally done tinkering with bash
>  completion support for this week.  Total of 12 patches.

Thanks.  I saw a funky behaviour when I tried this:

	$ git pull . ap<TAB>

==>
	$ git pull . apfatal: Not a git repository: '.'


^ permalink raw reply

* Re: Mozilla, git and Windows
From: Jon Smirl @ 2006-11-28  1:35 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Andy Whitcroft, Git Mailing List
In-Reply-To: <20061127221338.GP7201@pasky.or.cz>

On 11/27/06, Petr Baudis <pasky@suse.cz> wrote:
> On Mon, Nov 27, 2006 at 05:13:10PM CET, Jon Smirl wrote:
> > The SVN version of the Mozilla repository is about 3GB. It takes
> > around a week of CPU time for svnimport to process it.
>
> Is there a reason why a SVN importer would _have_ to take _longer_ than
> a CVS importer? I'd expect the opposite from an optimized importer since
> you don't have to guess the changesets...

These import programs take forever because they fork off git, SVN or
CVS millions of times. It really does take a week to fork a CVS
process that many times. It's not the application code that is taking
a week to run, it is the millions of forks.

As was mentioned in the thread about doing CVS to git import, the
trick is to write your own CVS file parser, parse the file once (not
once for each revision) and output all of the revisions to the git
database in a single pass. When code is structured that way I can
import the whole Mozilla repository into git in two hours. The
fast-import back end also works with out forking, it just listens to
command and stdin and acts on them, all of the commands are implement
in a single binary.

The speed of fork in Linux is fine for most purposes, but it is not
fine if you are going to fork off good sized apps several million
times. When I measured those forks in oprofile, 60% of the CPU was
being consumed by the kernel.

-- 
Jon Smirl

^ permalink raw reply

* Re: Hyphens and hiding core commands
From: Carl Worth @ 2006-11-28  1:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vy7pwcsgp.fsf@assigned-by-dhcp.cox.net>

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

On Mon, 27 Nov 2006 16:42:14 -0800, Junio C Hamano wrote:
> I think you are teaching backwards.  Couldn't you start like this?
>
> 	"git commit" takes the list of paths you want to commit.

I've always started teaching with:

	git init-db
	git add file
	git commit -m "Initial commit"
	# edit file
	git commit -a -m "edit file"

And at that point I've either apologized about "-a" or been asked a
question about it. Every time.

But it's the tutorial we were talking about:

	http://www.kernel.org/pub/software/scm/git/docs/tutorial.html

That has 6 examples of commit being used, and all of them are with
"commit -a". What "git commit" does without -a must certainly be a
question in the mind of any reader, (the tutorial doesn't mention
anything).

And unlike when I'm teaching in person, when the reader reads the
tutorial, there's no person to explain the situation. The reader might
just remain confused, or they might consult the documentation for
git-commit and find a first sentence that says:

       Updates the index file for given paths, or all modified files
       if -a is specified, and makes a commit object.

And then we're back to the question of "what the heck is an index, and
why do I care?".

If the "commit the index" operation were moved to a non-default
command-line option of git-commit, then the commit command could be
explained without having to introduce the notion of the index at
all. This would be a good thing. I don't think we have any
introductory documentation that introduces the index until the "core
tutorial" and my goal here is to allow an introduction to using git
that doesn't require that level of detail.

One of the arguments I got here on the git mailing list when I first
brought up these kinds of "hide the index" proposals, (back in
February or so), was that the index is essential to understand for
merging anyway, and that I should just teach it early on.

I've tried the "teach it early" approach in the months since and found
it to be largely a failure. Most new users react by deciding that git
is more complicated than other systems, or that it's more specialized
or not targeted at someone with their needs.

As for merging, I'd rather introduce the new "git resolve" syntax so
that merging could be explained in terms of the working tree without
having to fully understand the index either.

If we could fix "git commit" and add "git resolve" I think we would
most of the confusion/complaints that I've encountered in 8 months of
teaching git. There would still be some aspects of "git diff" that are
potentially confusing without understanding the index, but that's
been much less of a problem than "commit -a" in my experience.

-Carl

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH] Teach git-branch howto rename a branch
From: Lars Hjemli @ 2006-11-28  2:01 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

This adds a '--rename' option to git branch. If specified, branch
creation becomes branch renaming.

With a single branchname, the current branch is renamed and .git/HEAD is
updated.

With two branchnames, the second name is renamed to the first.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---

This seems to do the right thing for both refs and reflogs, but 'make test' 
probably should be expanded with some evil test-cases to confirm my manual
testing.


 builtin-branch.c |   30 ++++++++++-
 refs.c           |  162 ++++++++++++++++++++++++++++++++++++++++++++++--------
 refs.h           |    3 +
 3 files changed, 171 insertions(+), 24 deletions(-)

diff --git a/builtin-branch.c b/builtin-branch.c
index 3d5cb0e..2a21263 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -245,9 +245,29 @@ static void create_branch(const char *name, const char *start,
 		die("Failed to write ref: %s.", strerror(errno));
 }
 
+static void rename_branch(const char *oldname, const char *newname, int force)
+{
+	char oldref[PATH_MAX], newref[PATH_MAX];
+	unsigned char sha1[20];
+
+	snprintf(oldref, sizeof oldref, "refs/heads/%s", oldname);
+	if (check_ref_format(oldref))
+		die("Invalid branch name: %s", oldref);
+
+	snprintf(newref, sizeof newref, "refs/heads/%s", newname);
+	if (check_ref_format(newref))
+		die("Invalid branch name: %s", newref);
+
+	if (resolve_ref(newref, sha1, 1, NULL) && !force)
+		die("A branch named '%s' already exists.\n", newname);
+
+	if (!rename_ref(oldref, newref) && !strcmp(oldname, head))
+		create_symref("HEAD", newref);
+}
+
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
-	int delete = 0, force_delete = 0, force_create = 0;
+	int delete = 0, rename = 0, force_delete = 0, force_create = 0;
 	int verbose = 0, abbrev = DEFAULT_ABBREV;
 	int reflog = 0;
 	int kinds = REF_LOCAL_BRANCH;
@@ -277,6 +297,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			force_create = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--rename")) {
+			rename = 1;
+			continue;
+		}
 		if (!strcmp(arg, "-r")) {
 			kinds = REF_REMOTE_BRANCH;
 			continue;
@@ -311,6 +335,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		delete_branches(argc - i, argv + i, force_delete);
 	else if (i == argc)
 		print_ref_list(kinds, verbose, abbrev);
+	else if (rename && (i == argc - 1))
+		rename_branch(head, argv[i], force_create);
+	else if (rename && (i == argc - 2))
+		rename_branch(argv[i + 1], argv[i], force_create);
 	else if (i == argc - 1)
 		create_branch(argv[i], head, force_create, reflog);
 	else if (i == argc - 2)
diff --git a/refs.c b/refs.c
index 0e156c5..1cb610f 100644
--- a/refs.c
+++ b/refs.c
@@ -534,6 +534,29 @@ static int remove_empty_directories(char *file)
 	return remove_empty_dir_recursive(path, len);
 }
 
+static int is_refname_available(const char *ref, const char *oldref, 
+				struct ref_list *list, int quiet)
+{
+	int namlen = strlen(ref); /* e.g. 'foo/bar' */
+	while (list) {
+		/* list->name could be 'foo' or 'foo/bar/baz' */
+		if (!oldref || strcmp(oldref, list->name)) {
+			int len = strlen(list->name);
+			int cmplen = (namlen < len) ? namlen : len;
+			const char *lead = (namlen < len) ? list->name : ref;
+			if (!strncmp(ref, list->name, cmplen) && 
+			    lead[cmplen] == '/') { 
+				if (!quiet)
+					error("'%s' exists; cannot create '%s'", 
+					      list->name, ref);
+				return 0;
+			}
+		}
+		list = list->next;
+	}
+	return 1;
+}
+
 static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
 {
 	char *ref_file;
@@ -567,29 +590,14 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
 			orig_ref, strerror(errno));
 		goto error_return;
 	}
-	if (is_null_sha1(lock->old_sha1)) {
-		/* The ref did not exist and we are creating it.
-		 * Make sure there is no existing ref that is packed
-		 * whose name begins with our refname, nor a ref whose
-		 * name is a proper prefix of our refname.
-		 */
-		int namlen = strlen(ref); /* e.g. 'foo/bar' */
-		struct ref_list *list = get_packed_refs();
-		while (list) {
-			/* list->name could be 'foo' or 'foo/bar/baz' */
-			int len = strlen(list->name);
-			int cmplen = (namlen < len) ? namlen : len;
-			const char *lead = (namlen < len) ? list->name : ref;
-
-			if (!strncmp(ref, list->name, cmplen) &&
-			    lead[cmplen] == '/') {
-				error("'%s' exists; cannot create '%s'",
-				      list->name, ref);
-				goto error_return;
-			}
-			list = list->next;
-		}
-	}
+	/* When the ref did not exist and we are creating it,
+	 * make sure there is no existing ref that is packed
+	 * whose name begins with our refname, nor a ref whose
+	 * name is a proper prefix of our refname.
+	 */
+	if (is_null_sha1(lock->old_sha1) && 
+            !is_refname_available(ref, NULL, get_packed_refs(), 0))
+		goto error_return;
 
 	lock->lk = xcalloc(1, sizeof(struct lock_file));
 
@@ -700,6 +708,114 @@ int delete_ref(const char *refname, unsigned char *sha1)
 	return ret;
 }
 
+int rename_ref(const char *oldref, const char *newref)
+{
+	unsigned char sha1[20], orig_sha1[20];
+	int flag = 0, logmoved = 0;
+	struct ref_lock *lock;
+	char msg[PATH_MAX*2 + 100];
+	struct stat stat;
+	int log = !lstat(git_path("logs/%s", oldref), &stat);
+
+	if (!resolve_ref(oldref, orig_sha1, 1, &flag))
+		return error("refname %s not found", oldref);
+
+	if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
+		return 1;
+
+	if (!is_refname_available(newref, oldref, get_loose_refs(), 0))
+		return 1;
+
+	lock = lock_ref_sha1_basic("tmp-renamed-ref", NULL, NULL);
+	if (!lock)
+		return error("unable to lock tmp-renamed-ref");
+	lock->force_write = 1;
+	if (write_ref_sha1(lock, orig_sha1, msg))
+		return error("unable to save current sha1 in tmp-renamed-ref");
+	if (log && rename(git_path("logs/%s", oldref), git_path("tmp-renamed-log")))
+		return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
+			oldref, strerror(errno));
+	
+	if (delete_ref(oldref, orig_sha1)) {
+		error("unable to delete old %s", oldref);
+		goto rollback;
+	}
+
+	if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1)) {
+		if (errno==EISDIR) {
+			if (remove_empty_directories(git_path("%s", newref))) {
+				error("Directory not empty: %s", newref);
+				goto rollback;
+			}
+		} else {
+			error("unable to delete existing %s", newref);
+			goto rollback;
+		}
+	} 
+
+	if (log && safe_create_leading_directories(git_path("logs/%s", newref))) {
+		error("unable to create directory for %s", newref);
+		goto rollback;
+	}
+
+ retry:
+	if (log && rename(git_path("tmp-renamed-log"), git_path("logs/%s", newref))) {
+		if (errno==EISDIR) {
+			if (remove_empty_directories(git_path("logs/%s", newref))) {
+				error("Directory not empty: logs/%s", newref);
+				goto rollback;
+			}
+			goto retry;
+		} else {
+			error("unable to move logfile tmp-renamed-log to logs/%s: %s",
+				newref, strerror(errno));
+			goto rollback;
+		}
+	}
+	logmoved = log;
+
+	lock = lock_ref_sha1_basic(newref, NULL, NULL);	
+	if (!lock) {
+		error("unable to lock %s for update", newref);
+		goto rollback;
+	}
+
+	snprintf(msg, sizeof msg, "renamed from %s to %s", oldref, newref);
+	lock->force_write = 1;
+	hashcpy(lock->old_sha1, orig_sha1);
+	if (write_ref_sha1(lock, orig_sha1, msg)) {
+		error("unable to write current sha1 into %s", newref);
+		goto rollback;
+	}
+
+	return 0;
+
+ rollback:
+	lock = lock_ref_sha1_basic(oldref, NULL, NULL);	
+	if (!lock) {
+		error("unable to lock %s for rollback", oldref);
+		goto rollbacklog;
+	}
+
+	lock->force_write = 1;
+	flag = log_all_ref_updates;
+	log_all_ref_updates = 0;
+	if (write_ref_sha1(lock, orig_sha1, NULL))
+		error("unable to write current sha1 into %s", oldref);
+	log_all_ref_updates = flag;
+
+ rollbacklog:
+	if (logmoved && rename(git_path("logs/%s", newref), git_path("logs/%s", oldref)))
+		error("unable to restore logfile %s from %s: %s",
+			oldref, newref, strerror(errno));
+	if (!logmoved && log && 
+	    rename(git_path("tmp-renamed-log"), git_path("logs/%s", oldref)))
+		error("unable to restore logfile %s from tmp-renamed-log: %s",
+			oldref, strerror(errno));
+
+	return 1;
+}
+
 void unlock_ref(struct ref_lock *lock)
 {
 	if (lock->lock_fd >= 0) {
diff --git a/refs.h b/refs.h
index a57d437..61419db 100644
--- a/refs.h
+++ b/refs.h
@@ -44,4 +44,7 @@ extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned
 /** Returns 0 if target has the right format for a ref. **/
 extern int check_ref_format(const char *target);
 
+/** rename ref, return 0 on success **/
+extern int rename_ref(const char *oldref, const char *newref);
+
 #endif /* REFS_H */
-- 
1.4.4.1.gf64d

^ permalink raw reply related

* Re: Hyphens and hiding core commands
From: Junio C Hamano @ 2006-11-28  2:18 UTC (permalink / raw)
  To: Carl Worth; +Cc: git
In-Reply-To: <878xhwwdyj.wl%cworth@cworth.org>

Carl Worth <cworth@cworth.org> writes:

> On Mon, 27 Nov 2006 16:42:14 -0800, Junio C Hamano wrote:
>> I think you are teaching backwards.  Couldn't you start like this?
>>
>> 	"git commit" takes the list of paths you want to commit.
> ...

> If the "commit the index" operation were moved to a non-default
> command-line option of git-commit, then the commit command could be
> explained without having to introduce the notion of the index at
> all.

Read what I wrote again.  You can explain it without talking
about index at all.  I really do not think you need to break
"git commit" nor rename "update-index" to "resolve" to explain
things to new people.

The tutorial might be better reworked not to start talking about
-a but start building small project from a newly created
hello.c, git add it, and "git commit" (the first commit), then
edit hello.c and "git commit hello.c" (the second commit).

Perhaps.

Enough about "git commit -a" for tonight.

^ permalink raw reply

* Re: SEGV when lookup_* returns NULL
From: Morten Welinder @ 2006-11-28  2:23 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, Martin Waitz, git
In-Reply-To: <7v3b84e8cg.fsf@assigned-by-dhcp.cox.net>

> Why?  You would certainly install your own die() handler by that
> time I presume?

Likely, but short of exiting or using longjmp/setjmp what can you do
in such a "die"?  Not much.  And most GUI users will be unhappy
with the exit approach.

If there is any chance that the error is not the programmer's fault, a
nice library ought to pass the error back somehow.


^ permalink raw reply

* Re: git and bzr
From: Linus Torvalds @ 2006-11-28  2:57 UTC (permalink / raw)
  To: Joseph Wakeling; +Cc: bazaar-ng, git
In-Reply-To: <456B7C6A.80104@webdrake.net>



On Tue, 28 Nov 2006, Joseph Wakeling wrote:
>
> First off a really dumb one: how do I identify myself to git, i.e. give
> it a name and email address?  Currently it uses my system identity,
> My Name <username@computer.(none)>.  I haven't found any equivalent of
> the bzr whoami command.

Depending on whether you like editing config files by hand or not, you 
would either just edit your ~/.gitconfig file and add a section like:

	[user]
		name = My Name Goes Here
		email = myemail@work.com

or you would use "git repo-config" to do it for you. Personally, I find it 
easier to just edit the .gitconfig file directly, since the config file 
syntax is actually rather pleasant, but if you want to do it with a git 
command, you'd do

	git repo-config --global user.name "Joseph Wakeling"
	git repo-config --global user.email joseph.wakeling@webdrake.net

(where the "--global" just tells repo-config to use the user-global 
~/.gitconfig file - you can also do this on a per-repository basis in the 
repository .git/config file if you want to have different identities for 
different repositories).

> Now to more serious business.  One of the main operational differences I
> see as a new user is that bzr defaults to setting up branches in
> different locations, whereas git by default creates a repository where
> branches are different versions of the directory contents and switching
> branches *changes* the directory contents.  bzr branch seems to be
> closer to git-clone than git-branch (N.B. I have never used bzr repos so
> might not be making a fair comparison).

You can do either, it's almost purely a matter of taste.

Using a local branch and switching between them in place has some 
advantages once you get used to it: most notably you can trivially use git 
commands that work on data from different branches at the same time. So 
with that kind of setup it's very natural to do things like "show me 
everything that is in branch 'x', but _not_ in branch 'y'", and once you 
get used to that, you really appreaciate it.

But at the same time, if you want to actually keep several branches 
checked out at the same time, and prefer to work on them that way, just 
use "git clone" to create the other branch instead. It really is just a 
matter of taste.

I suspect that most people tend to end up using the "multiple branches in 
the same directory and switching between them" approach after a time, but 
that's really just an unsubstantiated feeling, and it certainly isn't 
something that git forces on you. 

> With this in mind, is there any significance to the "master" branch (is
> it intended e.g. to indicate a git repository's "stable" version
> according to the owner?), or is this just a convenient default name?
> Could I delete or rename it?  Using bzr I would normally give the
> central branch(*) the name of the project.

It's just a convenient default name, and it has no real meaning otherwise. 
Feel free to rename it any way you want (just make sure to edit HEAD to 
point to the new name is you rename it by hand).

> Any other useful comments that can be made to a bzr user about working
> with this difference, positive or negative aspects of it?

There should be no difference, although since everybody seems to use 
"master" by default, the documentation is probably geared towards it, and 
who knows, maybe you'll hit a bug that nobody else noticed just because 
everybody else had a "master" branch, and some silly script had it 
hardcoded.

> Next question ... one of the reasons I started seriously thinking about
> git was that in the VCS comparison discussion, it was noted that git is
> a lot more flexible than bzr in terms of how it can track data (e.g. the
> git pickaxe command, although I understand that's not in the released
> version [1.4.4.1] yet?).

pickaxe wasn't in the released version back when the discussions were 
raging, but it's there now. Except it's really called "git blame" these 
days (and "git annotate") since it's taken over both of those duties.

However...

> A frustration with bzr is that pulling or
> merging patches from another branch or repo requires them to share the
> same HEAD.  Is this a requirement in git or can I say, "Hey, I like that
> particular function in project XXX, I'm going to pull that individual
> bit of code and its development history into project YYY"?

... it's not _quite_ that smart. It will only look for sources to new 
functions from existing sources in the tree that preceded the commit that 
added the function, so it will _not_ see it coming from another branch or 
another project entirely.

So when you ask for code annotations (use the "-C" flag to see code moved 
across from other files), it will still limit itself to just a particular 
input set, and not go gallivating over all possible branches and projects 
you might have in your repository.

It wouldn't be theoretically impossible to do, but it would be 
prohibitively expensive (where do you draw the line for what to look at). 

So git won't do quite what you ask for.

> Last off (for now, I'm sure I'll think of more): is there any easy (or
> difficult) way to effectively import version history from a bzr
> repository, and vice versa?

There's a "archimport", but I assume bzr has long since broken 
compatibility with arch (and/or just extended things so much as to not be 
importable with that any more), regardless of any origin. But it might be 
a good starting point, at least.

			Linus




^ permalink raw reply

* Re: Show remote branches on gitweb
From: Pazu @ 2006-11-28  2:59 UTC (permalink / raw)
  To: git
In-Reply-To: <ekfe15$a48$1@sea.gmane.org>

Jakub Narebski <jnareb <at> gmail.com> writes:

> What about tags (refs/tags/), which shouldn't be here?

Yeah, I just noticed that when I pointed gitweb to git's own repository (my
project's repository currently has no tags). I've added a "next if $name =~
m!^refs/tags/!;" for now.

> Besides, it is quick'n'dirty solution; I'm not against having it as a patch
> in git mailing list archives, but I'd rather not have it there.

Yes, it's quick and dirty. I didn't mean to have it published anywhere (and to
anyone reading this from the archives: please don't use that ugly, quick, and
really dirty patch).

I posted it as a way to say that I'm one more happy git user. While one could
say that hacking gitweb to achieve happiness is cheating, the fact that I
*could* do that easily, even when I barely understand perl, is a really big plus
for me. You guys rock, really.

-- Pazu

^ permalink raw reply

* Re: Hyphens and hiding core commands
From: Theodore Tso @ 2006-11-28  5:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Carl Worth, git
In-Reply-To: <7vk61gcnzl.fsf@assigned-by-dhcp.cox.net>

On Mon, Nov 27, 2006 at 06:18:54PM -0800, Junio C Hamano wrote:
> Read what I wrote again.  You can explain it without talking
> about index at all.  I really do not think you need to break
> "git commit" nor rename "update-index" to "resolve" to explain
> things to new people.

I think you're both right, and talking past each other to a certain
extent.  Yes, pedagogically it would be better to talk about "git
commit Makefile hello.c ..."; and "git commit -a" as a short-cut to
not have to list all of the files explicitly.

> The tutorial might be better reworked not to start talking about
> -a but start building small project from a newly created
> hello.c, git add it, and "git commit" (the first commit), then
> edit hello.c and "git commit hello.c" (the second commit).
> 
> Perhaps.

Carl was saying that the totorial should be changed to do this.  I
would change "perhaps" to "DEFINITELY".  

I would go further and argue that the man page for git-commit should
be changed to list the:

	git commit file ...
and
	git -a

alternatives first, and then talk about the index in a subsequent
paragraph (perhaps with a note that the first two usages are best for
novice users) might also be a good idea.  Yes, the man page is
supposed to be a reference, but some novice users do bother to try to
learn by reading the man page (shock!  horror!), and it might be good
if they don't run screaming into the night.

But hey, there's room for many distributed SCM's, and we can always
let those users use Mercurial and be happy....  (Just know that
project leaders who are worried about keeping their developer base
broad might choose Mercurial because it has a gentler learning curve
--- and that perhaps a few simple documentation changes plus some
syntatic sugar might make git much more attractive to them and to
novice git users.)


^ permalink raw reply

* [PATCH 1/2] git-svn: enable delta transfers during fetches when using SVN:: libs
From: Eric Wong @ 2006-11-28  5:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Pazu
In-Reply-To: <loom.20061124T143148-286@post.gmane.org>

This should drastically reduce bandwidth used for network
transfers.  This is not enabled for file:// repositories by
default because of the increased CPU usage and I/O needed.

GIT_SVN_DELTA_FETCH may be set to a true value to enable or
false (0) to disable delta transfers regardless of the
repository type.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
 git-svn.perl |  194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 189 insertions(+), 5 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index d5d9c49..9b86d91 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -68,7 +68,7 @@ my ($_revision,$_stdin,$_no_ignore_ext,$
 	$_limit, $_verbose, $_incremental, $_oneline, $_l_fmt, $_show_commit,
 	$_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m,
 	$_merge, $_strategy, $_dry_run, $_ignore_nodate, $_non_recursive,
-	$_username, $_config_dir, $_no_auth_cache);
+	$_username, $_config_dir, $_no_auth_cache, $_xfer_delta);
 my (@_branch_from, %tree_map, %users, %rusers, %equiv);
 my ($_svn_co_url_revs, $_svn_pg_peg_revs);
 my @repo_path_split_cache;
@@ -2675,6 +2675,9 @@ sub libsvn_load {
 		require SVN::Ra;
 		require SVN::Delta;
 		push @SVN::Git::Editor::ISA, 'SVN::Delta::Editor';
+		push @SVN::Git::Fetcher::ISA, 'SVN::Delta::Editor';
+		*SVN::Git::Fetcher::process_rm = *process_rm;
+		*SVN::Git::Fetcher::safe_qx = *safe_qx;
 		my $kill_stupid_warnings = $SVN::Node::none.$SVN::Node::file.
 					$SVN::Node::dir.$SVN::Node::unknown.
 					$SVN::Node::none.$SVN::Node::file.
@@ -2827,6 +2830,13 @@ sub libsvn_connect {
 	                      config => $config,
 	                      pool => SVN::Pool->new,
 	                      auth_provider_callbacks => $callbacks);
+
+	my $df = $ENV{GIT_SVN_DELTA_FETCH};
+	if (defined $df) {
+		$_xfer_delta = $df;
+	} else {
+		$_xfer_delta = ($url =~ m#^file://#) ? undef : 1;
+	}
 	$ra->{svn_path} = $url;
 	$ra->{repos_root} = $ra->get_repos_root;
 	$ra->{svn_path} =~ s#^\Q$ra->{repos_root}\E/*##;
@@ -2915,6 +2925,24 @@ sub process_rm {
 }
 
 sub libsvn_fetch {
+	$_xfer_delta ? libsvn_fetch_delta(@_) : libsvn_fetch_full(@_);
+}
+
+sub libsvn_fetch_delta {
+	my ($last_commit, $paths, $rev, $author, $date, $msg) = @_;
+	my $pool = SVN::Pool->new;
+	my $ed = SVN::Git::Fetcher->new({ c => $last_commit, ra => $SVN,
+	                                  paths => $paths });
+	my $reporter = $SVN->do_update($rev, '', 1, $ed, $pool);
+	my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();
+	my (undef, $last_rev, undef) = cmt_metadata($last_commit);
+	$reporter->set_path('', $last_rev, 0, @lock, $pool);
+	$reporter->finish_report($pool);
+	$pool->clear;
+	libsvn_log_entry($rev, $author, $date, $msg, [$last_commit]);
+}
+
+sub libsvn_fetch_full {
 	my ($last_commit, $paths, $rev, $author, $date, $msg) = @_;
 	open my $gui, '| git-update-index -z --index-info' or croak $!;
 	my @amr;
@@ -3133,7 +3161,11 @@ sub libsvn_find_parent_branch {
 		unlink $GIT_SVN_INDEX;
 		print STDERR "Found branch parent: ($GIT_SVN) $parent\n";
 		sys(qw/git-read-tree/, $parent);
-		return libsvn_fetch($parent, $paths, $rev,
+		# I can't seem to get do_switch() to work correctly with
+		# the SWIG interface (TypeError when passing switch_url...),
+		# so we'll unconditionally bypass the delta interface here
+		# for now
+		return libsvn_fetch_full($parent, $paths, $rev,
 					$author, $date, $msg);
 	}
 	print STDERR "Nope, branch point not imported or unknown\n";
@@ -3153,9 +3185,19 @@ sub libsvn_new_tree {
 		return $log_entry;
 	}
 	my ($paths, $rev, $author, $date, $msg) = @_;
-	open my $gui, '| git-update-index -z --index-info' or croak $!;
-	libsvn_traverse($gui, '', $SVN->{svn_path}, $rev);
-	close $gui or croak $?;
+	if ($_xfer_delta) {
+		my $pool = SVN::Pool->new;
+		my $ed = SVN::Git::Fetcher->new({paths => $paths, ra => $SVN});
+		my $reporter = $SVN->do_update($rev, '', 1, $ed, $pool);
+		my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();
+		$reporter->set_path('', $rev, 1, @lock, $pool);
+		$reporter->finish_report($pool);
+		$pool->clear;
+	} else {
+		open my $gui, '| git-update-index -z --index-info' or croak $!;
+		libsvn_traverse($gui, '', $SVN->{svn_path}, $rev);
+		close $gui or croak $?;
+	}
 	return libsvn_log_entry($rev, $author, $date, $msg);
 }
 
@@ -3325,6 +3367,148 @@ sub copy_remote_ref {
 				"refs/remotes/$GIT_SVN on $origin\n";
 	}
 }
+package SVN::Git::Fetcher;
+use vars qw/@ISA/;
+use strict;
+use warnings;
+use Carp qw/croak/;
+use IO::File qw//;
+
+# file baton members: path, mode_a, mode_b, pool, fh, blob, base
+sub new {
+	my ($class, $git_svn) = @_;
+	my $self = SVN::Delta::Editor->new;
+	bless $self, $class;
+	open my $gui, '| git-update-index -z --index-info' or croak $!;
+	$self->{gui} = $gui;
+	$self->{c} = $git_svn->{c} if exists $git_svn->{c};
+	if (my $p = $git_svn->{paths} && $git_svn->{ra}) {
+		my $s = $git_svn->{ra}->{svn_path};
+		$s = length $s ? qr#^/\Q$s\E/# : qr#^/#;
+		$self->{paths} = { map { my $x = $_;
+		                         $x =~ s/$s//;
+		                         $x => $p->{$_} } keys %$p };
+	}
+	require Digest::MD5;
+	$self;
+}
+
+sub delete_entry {
+	my ($self, $path, $rev, $pb) = @_;
+	process_rm($self->{gui}, $self->{c}, $path);
+	undef;
+}
+
+sub open_file {
+	my ($self, $path, $pb, $rev) = @_;
+	my ($mode, $blob) = (safe_qx('git-ls-tree',$self->{c},'--',$path)
+	                     =~ /^(\d{6}) blob ([a-f\d]{40})\t/);
+	{ path => $path, mode_a => $mode, mode_b => $mode, blob => $blob,
+	  pool => SVN::Pool->new };
+}
+
+sub add_file {
+	my ($self, $path, $pb, $cp_path, $cp_rev) = @_;
+	{ path => $path, mode_a => 100644, mode_b => 100644,
+	  pool => SVN::Pool->new };
+}
+
+sub change_file_prop {
+	my ($self, $fb, $prop, $value) = @_;
+	if ($prop eq 'svn:executable') {
+		if ($fb->{mode_b} != 120000) {
+			$fb->{mode_b} = defined $value ? 100755 : 100644;
+		}
+	} elsif ($prop eq 'svn:special') {
+		$fb->{mode_b} = defined $value ? 120000 : 100644;
+	}
+	undef;
+}
+
+sub apply_textdelta {
+	my ($self, $fb, $exp) = @_;
+	my $fh = IO::File->new_tmpfile;
+	$fh->autoflush(1);
+	# $fh gets auto-closed() by SVN::TxDelta::apply(),
+	# (but $base does not,) so dup() it for reading in close_file
+	open my $dup, '<&', $fh or croak $!;
+	my $base = IO::File->new_tmpfile;
+	$base->autoflush(1);
+	if ($fb->{blob}) {
+		defined (my $pid = fork) or croak $!;
+		if (!$pid) {
+			open STDOUT, '>&', $base or croak $!;
+			print STDOUT 'link ' if ($fb->{mode_a} == 120000);
+			exec qw/git-cat-file blob/, $fb->{blob} or croak $!;
+		}
+		waitpid $pid, 0;
+		croak $? if $?;
+
+		if (defined $exp) {
+			seek $base, 0, 0 or croak $!;
+			my $md5 = Digest::MD5->new;
+			$md5->addfile($base);
+			my $got = $md5->hexdigest;
+			die "Checksum mismatch: $fb->{path} $fb->{blob}\n",
+			    "expected: $exp\n",
+			    "     got: $got\n" if ($got ne $exp);
+		}
+	}
+	seek $base, 0, 0 or croak $!;
+	$fb->{fh} = $dup;
+	$fb->{base} = $base;
+	[ SVN::TxDelta::apply($base, $fh, undef, $fb->{path}, $fb->{pool}) ];
+}
+
+sub close_file {
+	my ($self, $fb, $exp) = @_;
+	my $hash;
+	my $path = $fb->{path};
+	if (my $fh = $fb->{fh}) {
+		seek($fh, 0, 0) or croak $!;
+		my $md5 = Digest::MD5->new;
+		$md5->addfile($fh);
+		my $got = $md5->hexdigest;
+		die "Checksum mismatch: $path\n",
+		    "expected: $exp\n    got: $got\n" if ($got ne $exp);
+		seek($fh, 0, 0) or croak $!;
+		if ($fb->{mode_b} == 120000) {
+			read($fh, my $buf, 5) == 5 or croak $!;
+			$buf eq 'link ' or die "$path has mode 120000",
+			                       "but is not a link\n";
+		}
+		defined(my $pid = open my $out,'-|') or die "Can't fork: $!\n";
+		if (!$pid) {
+			open STDIN, '<&', $fh or croak $!;
+			exec qw/git-hash-object -w --stdin/ or croak $!;
+		}
+		chomp($hash = do { local $/; <$out> });
+		close $out or croak $!;
+		close $fh or croak $!;
+		$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
+		close $fb->{base} or croak $!;
+	} else {
+		$hash = $fb->{blob} or die "no blob information\n";
+	}
+	$fb->{pool}->clear;
+	my $gui = $self->{gui};
+	print $gui "$fb->{mode_b} $hash\t$path\0" or croak $!;
+	print "\t", $self->{paths}->{$path}->action,
+	      "\t$path\n" if defined $self->{paths}->{$path};
+	undef;
+}
+
+sub abort_edit {
+	my $self = shift;
+	close $self->{gui};
+	$self->SUPER::abort_edit(@_);
+}
+
+sub close_edit {
+	my $self = shift;
+	close $self->{gui} or croak;
+	$self->SUPER::close_edit(@_);
+}
 
 package SVN::Git::Editor;
 use vars qw/@ISA/;
-- 
1.4.4.1.g22a08

^ permalink raw reply related


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