threads / rfc / 7626

[RFC] git-clone: add --track <headname> support

Subject: [RFC] git-clone: add --track <headname> support

## tl;dr

9 messages between Apr 12, 2007 and Apr 13, 2007.

replies: 8people: 3as markdown or json

Martin Langhoff· Apr 12, 2007, 10:08 UTC · lore

Add support for a simplified workflow where users want to clone and start working on a head that is different from the HEAD of the repository.

Calling
   git-clone --track maint <repo>
Is equivalent to
   git-clone <repo> mydir
   cd mydir
   git-checkout --track -b maint origin/maint
--

Not sure if Junio wants this, but if I am going to migrate away from cogito, I'd like these common operations to be dead simple.

This is something cogito supports using the <repo>#branchname syntax. I am pretty sure git supports it when fetching but alas, no longer for cloning.

And if we want it, there are 2 things I'd ask review for
 - The --track parameter handling - I merely copied the 
   handling for other parameters. Clearly shell doesn't
   do this very elegantly, or at least we don't. 
 - The block that defines head_points_at (@360-370) looks 
   very brittle so I didn't want to mess with it. 
---
 git-clone.sh |   39 +++++++++++++++++++++++++++------------
 1 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/git-clone.sh b/git-clone.sh
index e98e064..c7b3e99 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -14,7 +14,7 @@ die() {
 }
 
 usage() {
-	die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]"
+	die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--track <head>] [--depth <n>] [-n] <repo> [<dir>]"
 }
 
 get_repo_base() {
@@ -85,6 +85,7 @@ bare=
 reference=
 origin=
 origin_override=
+track=
 use_separate_remote=t
 depth=
 no_progress=
@@ -105,6 +106,11 @@ while
 		shift; template="--template=$1" ;;
 	*,--template=*)
 	  template="$1" ;;
+	1,--track) usage ;;
+	*,--track)
+		shift; track="$1" ;;
+	*,--track=*)
+	  track="$1" ;;
 	*,-q|*,--quiet) quiet=-q ;;
 	*,--use-separate-remote) ;;
 	*,--no-separate-remote)
@@ -344,17 +350,22 @@ if test -z "$bare" && test -f "$GIT_DIR/REMOTE_HEAD"
 then
 	# a non-bare repository is always in separate-remote layout
 	remote_top="refs/remotes/$origin"
-	head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
-	case "$head_sha1" in
-	'ref: refs/'*)
-		# Uh-oh, the remote told us (http transport done against
-		# new style repository with a symref HEAD).
-		# Ideally we should skip the guesswork but for now
-		# opt for minimum change.
-		head_sha1=`expr "z$head_sha1" : 'zref: refs/heads/\(.*\)'`
-		head_sha1=`cat "$GIT_DIR/$remote_top/$head_sha1"`
-		;;
-	esac
+	if test ! -z "$track" && test -f "refs/remotes/$origin/$track"
+	then
+		head_sha1=`cat "refs/remotes/$origin/$track"`
+	else
+		head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
+		case "$head_sha1" in
+		'ref: refs/'*)
+			# Uh-oh, the remote told us (http transport done against
+			# new style repository with a symref HEAD).
+			# Ideally we should skip the guesswork but for now
+			# opt for minimum change.
+			head_sha1=`expr "z$head_sha1" : 'zref: refs/heads/\(.*\)'`
+			head_sha1=`cat "$GIT_DIR/$remote_top/$head_sha1"`
+			;;
+		esac
+	fi
 
 	# The name under $remote_top the remote HEAD seems to point at.
 	head_points_at=$(
@@ -376,6 +387,10 @@ then
 		done
 		)
 	)
+	if test -n "$track" && test -f "$GIT_DIR/$remote_top/$track"
+	then
+		head_points_at="$track"
+	fi
 
 	# Write out remote.$origin config, and update our "$head_points_at".
 	case "$head_points_at" in
-- 
1.5.1.106.ga32037
Junio C Hamano· Apr 12, 2007, 10:23 UTC · re: Martin Langhoff · lore

Re: [RFC] git-clone: add --track <headname> support

Martin Langhoff <martin@catalyst.net.nz> writes:
Show 19 quoted lines
> Add support for a simplified workflow where users
> want to clone and start working on a head that is
> different from the HEAD of the repository.
>
> Calling
>
>    git-clone --track maint <repo>
>
> Is equivalent to
>
>    git-clone <repo> mydir
>    cd mydir
>    git-checkout --track -b maint origin/maint
>
> --
>
> Not sure if Junio wants this, but if I am going to migrate
> away from cogito, I'd like these common operations to be
> dead simple. 
I am not interested in moving people away from cogito ;-).

With the talk about making more things built-in, I think the changes to clone and fetch should be done by first rewriting git-clone as a very thin shell wrapper that essentially does:

	figure out the directory name to use
        mkdir that directory and cd into it
        run git init with appropriate options
        run git remote add with appropriate options
        run git fetch with appropriate options
        run git checkout with appropriate options (unless -n)

Also you might want to check "branch.autosetupmerge" config. It seems to be described in git-branch manual page without being listed in Documentation/config.txt, which is a bad that happend some time ago X-<.

It seems that today has been a day to discover many bads that happened some time ago for me X-<. I should quit and call it a day now...

Martin Langhoff· Apr 12, 2007, 21:32 UTC · re: Junio C Hamano · lore

Re: [RFC] git-clone: add --track <headname> support

Junio C Hamano wrote:
Show 6 quoted lines
> Martin Langhoff <martin@catalyst.net.nz> writes:
>> Not sure if Junio wants this, but if I am going to migrate
>> away from cogito, I'd like these common operations to be
>> dead simple. 
> 
> I am not interested in moving people away from cogito ;-).

Well... ;-) in any case, I suspect some of the semantics cogito uses are starting to break... it's kinda-supported-but-legacy.

So I think we need these niceties in core git for large projects. Right now we have an explosion of ways of doing things, and many of them error-prone. The basic idioms should be simple and fool-proof.

> With the talk about making more things built-in...

Can we not have something like this merged into the shell version? When the C version comes, the functionality can be modelled on this.

> Also you might want to check "branch.autosetupmerge" config.  It
> seems to be described in git-branch manual page without being
> listed in Documentation/config.txt, which is a bad that happend
> some time ago X-<.
Will to. Thanks.
> It seems that today has been a day to discover many bads that
> happened some time ago for me X-<.  I should quit and call it a
> day now...
Hope your next day is better. Hugs from NZ.
m
-- 
-----------------------------------------------------------------------
Martin @ Catalyst .Net .NZ  Ltd, PO Box 11-053, Manners St,  Wellington
WEB: http://catalyst.net.nz/           PHYS: Level 2, 150-154 Willis St
OFFICE: +64(4)916-7224  UK: 0845 868 5733 ext 7224  MOB: +64(21)364-017
      Make things as simple as possible, but no simpler - Einstein
-----------------------------------------------------------------------
Carl Worth· Apr 12, 2007, 16:34 UTC · re: Martin Langhoff · lore

Re: [RFC] git-clone: add --track <headname> support

On Thu, 12 Apr 2007 22:08:59 +1200, Martin Langhoff wrote:
> Not sure if Junio wants this, but if I am going to migrate
> away from cogito, I'd like these common operations to be
> dead simple.
Hi Martin,

Whether we're talking about cogito migration or not, I also want these operations to be dead simple. So I really appreciate seeing your efforts on this front.

> This is something cogito supports using the <repo>#branchname
> syntax. I am pretty sure git supports it when fetching
> but alas, no longer for cloning.

I seem to recall Linus complaining about the <repo>#branchname syntax because it allows for only one branch name. So one thing to think about is how to allow for multiple branches to be tracked while cloning, ("--track branch1 --track branch2" ?).

Separately, something I've always wanted is a succint way to advertise a complete specification of a branch that users could conveniently take, (read, "cut-and-paste, preferably with double-click"), and use whether they wanted to do any one of the following operations:

1. Make a new clone, and checkout that branch
2. Fetch that branch into an existing clone
3. Add that branch to an existing clone as something to start tracking

So, if you wanted to try to tackle that problem as well, that would be great. (It's basically an extension of your "git clone --track" idea---allowing it to be performed after a clone as well, but without any more complication in the user interface.)

For this, I think the <repo>#branch syntax is actually worthing thinking about. With it, the above three operations could be provided with operations something like:

	git clone <repo>#branch
	git fetch <repo>#branch
	git track <repo>#branch

Where this new git-track command would encompass a lot of the work that git-clone is doing currently. That is, the git-clone rewrite that Junio is envisioning could be implemented something like:

	mkdir <branch>
	cd <branch>
	git init-db
	git track <repo>#branch

In other words, most of the interesting stuff that git-clone does would still be available in an existing clone by using this new git-track command.

By the way, the <repo>#branch syntax isn't essential for what I'm describing here. This syntax does provide something that could be usefully provided to either git-clone or git-fetch as a single command. This is opposed to the current state where I have to say things like:

	If you've got a clone already, do: [*]
		git fetch <repo> branch:branch
		git checkout branch
	If you don't have a clone yet, do:
		git clone <repo>
		git checkout -b branch origin/branch

But whether or not <repo>#branch syntax is adopted, providing the post-init-db guts of git-track would still be useful, and it could still accept the same means of specifying multiple branches that git fetch accepts:

	git track <repo> branch1 branch2 ...

Anyway, there's some food for thought for anyone that's working on adding these kind of conveniences to git, (which I would find extremely valuable).

-Carl
Martin Langhoff· Apr 12, 2007, 21:46 UTC · re: Carl Worth · lore

Re: [RFC] git-clone: add --track <headname> support

Carl Worth wrote:
> Whether we're talking about cogito migration or not, I also want these
> operations to be dead simple. So I really appreciate seeing your
> efforts on this front.
Hi Carl! Yes - this stuff should be simple, and _really hard to fsck up_.
> I seem to recall Linus complaining about the <repo>#branchname syntax
> because it allows for only one branch name. So one thing to think
> about is how to allow for multiple branches to be tracked while
> cloning, ("--track branch1 --track branch2" ?).
That wouldn't be hard to implement. Actually, we could support both.
> Separately, something I've always wanted is a succint way to advertise
> a complete specification of a branch that users could conveniently
> take, (read, "cut-and-paste, preferably with double-click"), and use
> whether they wanted to do any one of the following operations:
(...)
Show 9 quoted lines
> For this, I think the <repo>#branch syntax is actually worthing
> thinking about. With it, the above three operations could be provided
> with operations something like:
> 
> 	git clone <repo>#branch
> 
> 	git fetch <repo>#branch
> 
> 	git track <repo>#branch
So you are proposing (or maybe I am re-interpreting things so) that
  git track <repo>#branch
should Do The Right Thing:
 - perform a clone if we aren't in a repo
 - set things up for tracking the branch if we are in a repo
I like the idea. :-)
Show 8 quoted lines
> Where this new git-track command would encompass a lot of the work
> that git-clone is doing currently. That is, the git-clone rewrite
> that Junio is envisioning could be implemented something like:
> 
> 	mkdir <branch>
> 	cd <branch>
> 	git init-db
> 	git track <repo>#branch

Oops - looks like we are talking about different things. What you write above can be done with "git-branch --track" on 1.5.1 so it's already in existence.

Show 15 quoted lines
> By the way, the <repo>#branch syntax isn't essential for what I'm
> describing here. This syntax does provide something that could be
> usefully provided to either git-clone or git-fetch as a single
> command. This is opposed to the current state where I have to say
> things like:
> 
> 	If you've got a clone already, do: [*]
> 
> 		git fetch <repo> branch:branch
> 		git checkout branch
> 
> 	If you don't have a clone yet, do:
> 
> 		git clone <repo>
> 		git checkout -b branch origin/branch

With my proposed git-track as a wrapper around git-clone _and_ git-branch --track, you only need to say

    To start working on foo, do
      git track <repo>#branch

And if the user has an existing checkout they can do if from inside the checkout, or perhaps better, saying

     git track --reference <myoldcheckout> <repo>#branch
to avoid the biiig download.
cheers,
m
-- 
-----------------------------------------------------------------------
Martin @ Catalyst .Net .NZ  Ltd, PO Box 11-053, Manners St,  Wellington
WEB: http://catalyst.net.nz/           PHYS: Level 2, 150-154 Willis St
OFFICE: +64(4)916-7224  UK: 0845 868 5733 ext 7224  MOB: +64(21)364-017
      Make things as simple as possible, but no simpler - Einstein
-----------------------------------------------------------------------
Carl Worth· Apr 12, 2007, 23:24 UTC · re: Martin Langhoff · lore

Re: [RFC] git-clone: add --track <headname> support

On Fri, 13 Apr 2007 09:46:45 +1200, Martin Langhoff wrote:
> Hi Carl! Yes - this stuff should be simple, and _really hard to fsck up_.

I definitely agree. I think the use case of "tracking some branch other than the default" is a really important one to make easy. Precisely because there are a lot of users who will initially use git for nothing other than this tracking, (not initially making commits, or pushing, etc.).

So we would do well if this initial exposure were really easy. And right now it's a bit too hard in my opinion, (in terms of commands, concepts, and syntax the user has to use).

Is this correct sequence for the operation in 1.5.1 ?
	git clone <repo>
	cd <project>
	git branch --track <branch> origin/<branch>
	git checkout branch
	git pull # as needed
I'd love to get that down to:
	git clone <something with <repo> and <branch>>
	cd <project>
	git pull # as needed
and then adding a subsequent branch to track would be:
	git track <something with <repo> and <branch>>
	git checkout <branch>
	git pull # as needed
> Oops - looks like we are talking about different things. What you write
> above can be done with "git-branch --track" on 1.5.1 so it's already in
> existence.

The mechanics are there, yes. All that's missing is the common <something> syntax which, as shown above, can be shared for both cloning originally and later adding a branch to track.

And <repo>#<branch> seems as good a <something> as anything else I could imagine.

Show 6 quoted lines
> With my proposed git-track as a wrapper around git-clone _and_
> git-branch --track, you only need to say
>
>     To start working on foo, do
>
>       git track <repo>#branch

Yeah, that's the idea. I had just planned on publishing the <repo>#branch part and the user would learn whether to pass that to "git clone" or "git track" as appropriate.

Making one command do either one seems a little too DWIM and error-prone to me. But whatever works, (and more importantly, whatever you can implement and get accepted).

-Carl
Martin Langhoff· Apr 12, 2007, 23:50 UTC · re: Carl Worth · lore

Re: [RFC] git-clone: add --track <headname> support

Carl Worth wrote:
Show 8 quoted lines
> Is this correct sequence for the operation in 1.5.1 ?
> 
> 	git clone <repo>
> 	cd <project>
> 	git branch --track <branch> origin/<branch>
> 	git checkout branch
> 	git pull # as needed
> 
Actually you don't need the git-checkout line
	git clone <repo>
	cd <project>
	git branch --track <branch> origin/<branch>
	git pull # as needed
Show 5 quoted lines
> I'd love to get that down to:
> 
> 	git clone <something with <repo> and <branch>>
> 	cd <project>
> 	git pull # as needed
That's what this patch does.
Show 5 quoted lines
> and then adding a subsequent branch to track would be:
> 
> 	git track <something with <repo> and <branch>>
> 	git checkout <branch>
> 	git pull # as needed

If your tree is reasonably clean (so that the implied git-checkout won't fail), then on 1.5.1 this Just Works

        git branch --track <branch> origin/<branch>
        git pull # as needed
cheers,
m
-- 
-----------------------------------------------------------------------
Martin @ Catalyst .Net .NZ  Ltd, PO Box 11-053, Manners St,  Wellington
WEB: http://catalyst.net.nz/           PHYS: Level 2, 150-154 Willis St
OFFICE: +64(4)916-7224  UK: 0845 868 5733 ext 7224  MOB: +64(21)364-017
      Make things as simple as possible, but no simpler - Einstein
-----------------------------------------------------------------------
Junio C Hamano· Apr 13, 2007, 00:28 UTC · re: Martin Langhoff · lore

Re: [RFC] git-clone: add --track <headname> support

Martin Langhoff <martin@catalyst.net.nz> writes:
Show 5 quoted lines
> If your tree is reasonably clean (so that the implied git-checkout won't
> fail), then on 1.5.1 this Just Works
>
>         git branch --track <branch> origin/<branch>
>         git pull # as needed

At least in theory, with branch.autosetupmerge, you shouldn't even have to say --track there. I've never used it myself, though.

Junio C Hamano· Apr 13, 2007, 03:50 UTC · re: Carl Worth · lore

Re: [RFC] git-clone: add --track <headname> support

Carl Worth <cworth@cworth.org> writes:
Show 11 quoted lines
> I'd love to get that down to:
>
> 	git clone <something with <repo> and <branch>>
> 	cd <project>
> 	git pull # as needed
>
> and then adding a subsequent branch to track would be:
>
> 	git track <something with <repo> and <branch>>
> 	git checkout <branch>
> 	git pull # as needed
I have a different suggestion.  Why not forget about 'git clone'?

After working in a clone of git.git, if you want to use the project history from another related repository, say Shawn's fastimport, what would you do?

Yes.  You add it with "git remote add".
	git remote add [options] gfi git://repo.or.cz/git/fastimport.git/

If you are _not_ working off of anybody else's work, how would you start a repository?

Yes, you just do "git init" in an empty repository.
	git init

And after that, in such a repository, certainly "git remote add" to add the FIRST remote would work, wouldn't it?

So, how about this two-command sequence instead?
 (0) Have this in $HOME/.gitconfig:
	$ cat >>$HOME/.gitconfig <<\EOF
	[branch]
        	autosetupmerge
	EOF
 (1) Prepare your working area and add the remote you want to
     track, with initial fetch:
        $ git remote add -f origin git://repo.or.cz/alt-git.git/
 (2) If you want to fork off of next, you can:
	$ git checkout -b next origin/next
The result of (2) reads like this:
	$ cat .git/config
        [remote "origin"]
                url = /opt/packrat/playpen/public/in-place/git/git.junio/
                fetch = +refs/heads/*:refs/remotes/origin/*
        [branch "next"]
                remote = origin
                merge = refs/heads/next

The [remote "origin"] section was added with (1), and [branch "next"] was done with (2). It means "When I am on 'next', if I did not give any parameter to 'git pull', I want a fetch from 'origin', and then get their 'next' branch merged.".

So after setting up your 'next' branch with a single command (2), when you are finished working in your 'next' and are ready to merge the corresponding 'next' branch of 'origin', you can just say 'git pull'. Isn't this what you want?

And I do not think trying to mix up (1) and (2) is a great idea. Whenever you are interested in yet another person's work, you do (1). And whenever you want to fork off of some remote tracking branch you have already done (1) for, you do (2). IOW, you can do more than one (2) for a single remote repository.

← back to recent threads