All of lore.kernel.org
 help / color / mirror / Atom feed
* defaults for where to merge from
@ 2007-02-28 14:53 Paolo Bonzini
  2007-02-28 15:13 ` Johannes Schindelin
  2007-02-28 15:22 ` Andy Parkins
  0 siblings, 2 replies; 48+ messages in thread
From: Paolo Bonzini @ 2007-02-28 14:53 UTC (permalink / raw)
  To: git

As can be seen from my other messages, I'm experimenting a little with 
git and trying to understand how its workflow compares with arch.  Right 
now, my procedure for branching off a remote archive is:

   git checkout -b branchname remote/upstreambranch
   git config --add branch.branchname.remote remote
   git config --add branch.branchname.merge refs/heads/upstreambranch

Is there a reason why "git branch" and "git checkout -b" should not 
automatically do the two "git-config --add"s when the source branch is 
remote?

In case the source branch is not remote, would "origin" be a good choice 
for the "branch.branchname.remote" variable?

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 14:53 defaults for where to merge from Paolo Bonzini
@ 2007-02-28 15:13 ` Johannes Schindelin
  2007-02-28 15:22 ` Andy Parkins
  1 sibling, 0 replies; 48+ messages in thread
From: Johannes Schindelin @ 2007-02-28 15:13 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: git

Hi,

On Wed, 28 Feb 2007, Paolo Bonzini wrote:

> As can be seen from my other messages, I'm experimenting a little with 
> git and trying to understand how its workflow compares with arch.  
> Right now, my procedure for branching off a remote archive is:
> 
>   git checkout -b branchname remote/upstreambranch
>   git config --add branch.branchname.remote remote
>   git config --add branch.branchname.merge refs/heads/upstreambranch
> 
> Is there a reason why "git branch" and "git checkout -b" should not 
> automatically do the two "git-config --add"s when the source branch is 
> remote?

I like it.

> In case the source branch is not remote, would "origin" be a good choice 
> for the "branch.branchname.remote" variable?

In case source branch is not a remote, I would not want that DWIMery.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 14:53 defaults for where to merge from Paolo Bonzini
  2007-02-28 15:13 ` Johannes Schindelin
@ 2007-02-28 15:22 ` Andy Parkins
  2007-02-28 15:30   ` Paolo Bonzini
                     ` (2 more replies)
  1 sibling, 3 replies; 48+ messages in thread
From: Andy Parkins @ 2007-02-28 15:22 UTC (permalink / raw)
  To: git; +Cc: Paolo Bonzini

On Wednesday 2007 February 28 14:53, Paolo Bonzini wrote:
> As can be seen from my other messages, I'm experimenting a little with
> git and trying to understand how its workflow compares with arch.  Right
> now, my procedure for branching off a remote archive is:
>
>    git checkout -b branchname remote/upstreambranch
>    git config --add branch.branchname.remote remote
>    git config --add branch.branchname.merge refs/heads/upstreambranch
>
> Is there a reason why "git branch" and "git checkout -b" should not
> automatically do the two "git-config --add"s when the source branch is
> remote?

I can see why that would be handy, but I often make short lived branches off a 
remote; and I wouldn't want my config cluttered up with branch defintions.

> In case the source branch is not remote, would "origin" be a good choice
> for the "branch.branchname.remote" variable?

No.  That would still reference a remote.  As in:

[remote "origin"]
        url = git://git.kernel.org/pub/scm/git/git.git
        fetch = refs/heads/master:refs/remotes/origin/master
[branch "master"]
        remote = origin
        merge = refs/heads/master

The remote = origin tells git to use the [remote "origin"] section.

I think what you want is something that I would like too.  If you specify "." 
to a git-pull it means to use the local repository not a remote.  It would be 
great if one could have:

[remote "origin"]
        url = git://git.kernel.org/pub/scm/git/git.git
        fetch = refs/heads/master:refs/remotes/origin/master
[branch "master"]
        remote = .
        merge = refs/remotes/origin/master

That way a "git pull" on master wouldn't need to make a remote connection in 
order to do a merge (which is the way I like it).  However, I remember there 
was a reason this wouldn't work, but I don't remember what it was :-)


Andy
-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:22 ` Andy Parkins
@ 2007-02-28 15:30   ` Paolo Bonzini
  2007-02-28 15:43     ` Andy Parkins
  2007-02-28 15:30   ` Julian Phillips
  2007-02-28 17:31   ` defaults for where to merge from Peter Baumann
  2 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-02-28 15:30 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git, Paolo Bonzini


>>    git checkout -b branchname remote/upstreambranch
>>    git config --add branch.branchname.remote remote
>>    git config --add branch.branchname.merge refs/heads/upstreambranch
>>
>> Is there a reason why "git branch" and "git checkout -b" should not
>> automatically do the two "git-config --add"s when the source branch is
>> remote?
> 
> I can see why that would be handy, but I often make short lived branches off a 
> remote; and I wouldn't want my config cluttered up with branch defintions.

So, is there a reason why the config not could be cleared out by branch -d?

(The "is there a reason" has the same meaning: it seems obvious to me, 
but I surely miss a lot of usecases because of inexperience).

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:22 ` Andy Parkins
  2007-02-28 15:30   ` Paolo Bonzini
@ 2007-02-28 15:30   ` Julian Phillips
  2007-02-28 15:46     ` Johannes Schindelin
  2007-02-28 17:31   ` defaults for where to merge from Peter Baumann
  2 siblings, 1 reply; 48+ messages in thread
From: Julian Phillips @ 2007-02-28 15:30 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git, Paolo Bonzini

On Wed, 28 Feb 2007, Andy Parkins wrote:

> On Wednesday 2007 February 28 14:53, Paolo Bonzini wrote:
>> As can be seen from my other messages, I'm experimenting a little with
>> git and trying to understand how its workflow compares with arch.  Right
>> now, my procedure for branching off a remote archive is:
>>
>>    git checkout -b branchname remote/upstreambranch
>>    git config --add branch.branchname.remote remote
>>    git config --add branch.branchname.merge refs/heads/upstreambranch
>>
>> Is there a reason why "git branch" and "git checkout -b" should not
>> automatically do the two "git-config --add"s when the source branch is
>> remote?
>
> I can see why that would be handy, but I often make short lived branches off a
> remote; and I wouldn't want my config cluttered up with branch defintions.

How about adding an option to tell checkout/branch that a tracking branch 
is wanted (-t perhaps) - or perhaps a way to say that you don't want to 
track the remote (depending on which is more popular)?

Certainly would be a nice feature to have ...

-- 
Julian

  ---
Meg Griffin:  Somebody's in the closet!
Jeff Foxworthy:  You know you're a redneck when your gun rack has a gun rack on it.
Stewie Griffin:  You suck!

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:30   ` Paolo Bonzini
@ 2007-02-28 15:43     ` Andy Parkins
  0 siblings, 0 replies; 48+ messages in thread
From: Andy Parkins @ 2007-02-28 15:43 UTC (permalink / raw)
  To: git; +Cc: Paolo Bonzini, Paolo Bonzini

On Wednesday 2007 February 28 15:30, Paolo Bonzini wrote:

> So, is there a reason why the config not could be cleared out by branch -d?

Good point.  I can't think of one.


Andy
-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:30   ` Julian Phillips
@ 2007-02-28 15:46     ` Johannes Schindelin
  2007-02-28 17:11       ` Paolo Bonzini
  2007-02-28 18:45       ` defaults for where to merge from Alex Riesen
  0 siblings, 2 replies; 48+ messages in thread
From: Johannes Schindelin @ 2007-02-28 15:46 UTC (permalink / raw)
  To: Julian Phillips; +Cc: Andy Parkins, git, Paolo Bonzini

Hi,

On Wed, 28 Feb 2007, Julian Phillips wrote:

> On Wed, 28 Feb 2007, Andy Parkins wrote:
> 
> > On Wednesday 2007 February 28 14:53, Paolo Bonzini wrote:
> > > As can be seen from my other messages, I'm experimenting a little with
> > > git and trying to understand how its workflow compares with arch.  Right
> > > now, my procedure for branching off a remote archive is:
> > > 
> > >    git checkout -b branchname remote/upstreambranch
> > >    git config --add branch.branchname.remote remote
> > >    git config --add branch.branchname.merge refs/heads/upstreambranch
> > > 
> > > Is there a reason why "git branch" and "git checkout -b" should not
> > > automatically do the two "git-config --add"s when the source branch is
> > > remote?
> > 
> > I can see why that would be handy, but I often make short lived 
> > branches off a remote; and I wouldn't want my config cluttered up with 
> > branch defintions.
> 
> How about adding an option to tell checkout/branch that a tracking 
> branch is wanted (-t perhaps) - or perhaps a way to say that you don't 
> want to track the remote (depending on which is more popular)?

I don't think that you should be forced to do it explicitely. If you want 
to merge in another branch, you can do that _explicitely_. So, defaulting 
to what most people want anyway is A Good Thing.

Just my 2 cents,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:46     ` Johannes Schindelin
@ 2007-02-28 17:11       ` Paolo Bonzini
  2007-02-28 18:06         ` Johannes Schindelin
  2007-02-28 18:45       ` defaults for where to merge from Alex Riesen
  1 sibling, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-02-28 17:11 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Julian Phillips, Andy Parkins, git

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


> I don't think that you should be forced to do it explicitely. If you want 
> to merge in another branch, you can do that _explicitely_. So, defaulting 
> to what most people want anyway is A Good Thing.

Here is a prototype patch to implement this functionality.  One problem 
is that config.c does not remove cleaned sections, so after "git-branch 
-d mybranch" one is left with a useless "[branch "mybranch"]" section in 
.git/config.  Other than this, it seems to work well in my experiments.

Paolo

[-- Attachment #2: git-builtin-branch-config.patch --]
[-- Type: text/plain, Size: 2528 bytes --]

diff --git a/builtin-branch.c b/builtin-branch.c
index d0179b0..4c42825 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -147,8 +147,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
 			error("Error deleting %sbranch '%s'", remote,
 			       argv[i]);
 			ret = 1;
-		} else
+		} else {
+			if (kinds == REF_LOCAL_BRANCH) {
+				/* Remove git-config keys.  */
+				char *config_key = xmalloc(strlen(argv[i]) + 15);
+				sprintf(config_key, "branch.%s.remote", argv[i]);
+				git_config_set(config_key, NULL);
+
+				sprintf(config_key, "branch.%s.merge", argv[i]);
+				git_config_set(config_key, NULL);
+				sprintf(config_key, "branch.%s", argv[i]);
+				git_config_set(config_key, NULL);
+			}
+
 			printf("Deleted %sbranch %s.\n", remote, argv[i]);
+		}
 
 	}
 
@@ -316,7 +330,7 @@ static void create_branch(const char *name, const char *start_name,
 	struct commit *commit;
 	unsigned char sha1[20];
 	char ref[PATH_MAX], msg[PATH_MAX + 20];
-	int forcing = 0;
+	int forcing = 0, remote = 0;
 
 	snprintf(ref, sizeof ref, "refs/heads/%s", name);
 	if (check_ref_format(ref))
@@ -335,6 +349,13 @@ static void create_branch(const char *name, const char *start_name,
 		hashcpy(sha1, start_sha1);
 	else if (get_sha1(start_name, sha1))
 		die("Not a valid object name: '%s'.", start_name);
+	else {
+		unsigned char remote_sha1[20];
+		remote = strchr(start_name, '/')
+			 && read_ref(mkpath("refs/remotes/%s", start_name),
+				     remote_sha1) != -1
+			 && !memcmp(sha1, remote_sha1, 20);
+	}
 
 	if ((commit = lookup_commit_reference(sha1)) == NULL)
 		die("Not a valid branch point: '%s'.", start_name);
@@ -354,6 +375,23 @@ static void create_branch(const char *name, const char *start_name,
 		snprintf(msg, sizeof msg, "branch: Created from %s",
 			 start_name);
 
+	if (remote) {
+		/* Branching off a remote branch.  Set up so that git-pull
+		   automatically merges from there.  */
+		char *config_key = xmalloc(strlen(name) + 15);
+		char *merge_value = xmalloc(strlen(start_name) + 10);
+		char *slash = strchr(start_name, '/');
+
+		char *remote_value = xstrdup(start_name);
+		remote_value[slash - start_name] = 0;
+		sprintf(config_key, "branch.%s.remote", name);
+		git_config_set(config_key, remote_value);
+
+		sprintf(merge_value, "refs/heads/%s", slash + 1);
+		sprintf(config_key, "branch.%s.merge", name);
+		git_config_set(config_key, merge_value);
+	}
+
 	if (write_ref_sha1(lock, sha1, msg) < 0)
 		die("Failed to write ref: %s.", strerror(errno));
 }

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:22 ` Andy Parkins
  2007-02-28 15:30   ` Paolo Bonzini
  2007-02-28 15:30   ` Julian Phillips
@ 2007-02-28 17:31   ` Peter Baumann
  2 siblings, 0 replies; 48+ messages in thread
From: Peter Baumann @ 2007-02-28 17:31 UTC (permalink / raw)
  To: git

Andy Parkins <andyparkins@gmail.com> schrieb:
> On Wednesday 2007 February 28 14:53, Paolo Bonzini wrote:
>> As can be seen from my other messages, I'm experimenting a little with
>> git and trying to understand how its workflow compares with arch.  Right
>> now, my procedure for branching off a remote archive is:
>>
>>    git checkout -b branchname remote/upstreambranch
>>    git config --add branch.branchname.remote remote
>>    git config --add branch.branchname.merge refs/heads/upstreambranch
>>
>> Is there a reason why "git branch" and "git checkout -b" should not
>> automatically do the two "git-config --add"s when the source branch is
>> remote?
>
> I can see why that would be handy, but I often make short lived branches off a 
> remote; and I wouldn't want my config cluttered up with branch defintions.
>
>> In case the source branch is not remote, would "origin" be a good choice
>> for the "branch.branchname.remote" variable?
>
> No.  That would still reference a remote.  As in:
>
> [remote "origin"]
>         url = git://git.kernel.org/pub/scm/git/git.git
>         fetch = refs/heads/master:refs/remotes/origin/master
> [branch "master"]
>         remote = origin
>         merge = refs/heads/master
>
> The remote = origin tells git to use the [remote "origin"] section.
>
> I think what you want is something that I would like too.  If you specify "." 
> to a git-pull it means to use the local repository not a remote.  It would be 
> great if one could have:
>
> [remote "origin"]
>         url = git://git.kernel.org/pub/scm/git/git.git
>         fetch = refs/heads/master:refs/remotes/origin/master
> [branch "master"]
>         remote = .
>         merge = refs/remotes/origin/master
>
> That way a "git pull" on master wouldn't need to make a remote connection in 
> order to do a merge (which is the way I like it).  However, I remember there 
> was a reason this wouldn't work, but I don't remember what it was :-)
>
>
> Andy

This doesn't work (AIUI). In your example you need to have a remote named ".",
which you havened (and I don't think . is valid for a remote name ).

But this works for me:

[remote "origin"]
        url = host:/path/to/your/repo
        fetch = refs/heads/*:refs/remotes/origin/*

[remote "local"]
        url = .
        fetch = refs/remotes/*:refs/remotes/*	# fetch into itself -> do nothing
						# needed to get the LHS of the fetch

[branch "testbranch"]
        remote = local
        merge = refs/remotes/origin/master	# specifying the LHS of the fetch


When on branch 'testbranch', a	'git pull local' merges
'refs/remotes/origin/master'.

Peter

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 17:11       ` Paolo Bonzini
@ 2007-02-28 18:06         ` Johannes Schindelin
  2007-03-01  7:52           ` [PATCH] defaults for where to merge from (take 2) Paolo Bonzini
  0 siblings, 1 reply; 48+ messages in thread
From: Johannes Schindelin @ 2007-02-28 18:06 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Julian Phillips, Andy Parkins, git

Hi,

On Wed, 28 Feb 2007, Paolo Bonzini wrote:

> 
> > I don't think that you should be forced to do it explicitely. If you 
> > want to merge in another branch, you can do that _explicitely_. So, 
> > defaulting to what most people want anyway is A Good Thing.
> 
> Here is a prototype patch to implement this functionality.  One problem 
> is that config.c does not remove cleaned sections, so after "git-branch 
> -d mybranch" one is left with a useless "[branch "mybranch"]" section in 
> .git/config.  Other than this, it seems to work well in my experiments.

I'd rather remove the complete section (However, that means that you have 
to introduce a function to do that in config.c) instead of unsetting 
several hardcoded values.

Also, the second part of your patch would be clearer (methinks) if you 
replaced the call to get_sha1() with dwim_ref(). You'd get the real 
refname for free...

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 15:46     ` Johannes Schindelin
  2007-02-28 17:11       ` Paolo Bonzini
@ 2007-02-28 18:45       ` Alex Riesen
  2007-02-28 19:56         ` Paolo Bonzini
  1 sibling, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-02-28 18:45 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Julian Phillips, Andy Parkins, git, Paolo Bonzini

On 2/28/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > How about adding an option to tell checkout/branch that a tracking
> > branch is wanted (-t perhaps) - or perhaps a way to say that you don't
> > want to track the remote (depending on which is more popular)?
>
> I don't think that you should be forced to do it explicitely. If you want
> to merge in another branch, you can do that _explicitely_. So, defaulting
> to what most people want anyway is A Good Thing.
>

As is an option to disable the feature. I.e. for scripts, which create branches
blindly, without knowing they working on a remote branch.
So, please, provide an option to do what git-checkout/git-branch did before:
which is just create the branch, nothing more.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 18:45       ` defaults for where to merge from Alex Riesen
@ 2007-02-28 19:56         ` Paolo Bonzini
  2007-03-01  0:07           ` Alex Riesen
  0 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-02-28 19:56 UTC (permalink / raw)
  To: Alex Riesen
  Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git, Paolo Bonzini


> As is an option to disable the feature. I.e. for scripts, which create 
> branches
> blindly, without knowing they working on a remote branch.
> So, please, provide an option to do what git-checkout/git-branch did 
> before:
> which is just create the branch, nothing more.

This does create the branch and nothing more.  It sets up "git pull" to 
do the obvious thing, but does not do anything more.  The branch is left 
in the same state than without the patch.  So the scripts will still 
work unless they create branches blindly, and blindly do a "git pull" 
expecting it to do the unobvious thing.

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-02-28 19:56         ` Paolo Bonzini
@ 2007-03-01  0:07           ` Alex Riesen
  2007-03-01  1:25             ` Johannes Schindelin
  0 siblings, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-03-01  0:07 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git, Paolo Bonzini

On 2/28/07, Paolo Bonzini <paolo.bonzini@lu.unisi.ch> wrote:
> > As is an option to disable the feature. I.e. for scripts, which create
> > branches
> > blindly, without knowing they working on a remote branch.
> > So, please, provide an option to do what git-checkout/git-branch did
> > before:
> > which is just create the branch, nothing more.
>
> This does create the branch and nothing more.

... except ...

> It sets up "git pull" to
> do the obvious thing, but does not do anything more.  The branch is left
> in the same state than without the patch.  So the scripts will still
> work unless they create branches blindly, and blindly do a "git pull"
> expecting it to do the unobvious thing.

Well, I find it unobvious for pull to magically starting merging.
Perhaps I'm using branch configuration in .git/config for too long,
and actually expect nothing to be merged if there is no appropriate
branch configuration.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  0:07           ` Alex Riesen
@ 2007-03-01  1:25             ` Johannes Schindelin
  2007-03-01  7:55               ` Alex Riesen
  0 siblings, 1 reply; 48+ messages in thread
From: Johannes Schindelin @ 2007-03-01  1:25 UTC (permalink / raw)
  To: Alex Riesen
  Cc: Paolo Bonzini, Julian Phillips, Andy Parkins, git, Paolo Bonzini

Hi,

On Thu, 1 Mar 2007, Alex Riesen wrote:

> Well, I find it unobvious for pull to magically starting merging.

Pull is _all_ about merging.

> Perhaps I'm using branch configuration in .git/config for too long, and 
> actually expect nothing to be merged if there is no appropriate branch 
> configuration.

It is not possible that you use that feature you described for too long, 
since it was not there in 1.4.x. There, whenever you said "git pull", it 
would try to blindly pull the default branch of the remote "origin", which 
might have been correct for the default branch (i.e. the branch 
automatically set up by git-clone), but not necessarily for the other 
branches.

And I want to stress a very important point: this automatic setting of the 
default remote and branch-to-merge should be _only_ triggered when 
branching from refs in $GIT_DIR/refs/remotes. Even if you _do_ branch them 
from scripts, I doubt that you'll break _anything_, except of course when 
the scripts are buggy to begin with.

There is a good chance that some user wants to merge something 
different, but in that case you have to specify what to merge _anyway_.

However, with the proposed behaviour, more new users would get less "Huh?" 
experiences.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH] defaults for where to merge from (take 2)
  2007-02-28 18:06         ` Johannes Schindelin
@ 2007-03-01  7:52           ` Paolo Bonzini
  0 siblings, 0 replies; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01  7:52 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

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


> I'd rather remove the complete section (However, that means that you have 
> to introduce a function to do that in config.c)

No problem.

> Also, the second part of your patch would be clearer (methinks) if you 
> replaced the call to get_sha1() with dwim_ref(). You'd get the real 
> refname for free...

Not only that, my previous version did not work if somebody specified
remotes/remote/upstreambranch instead of remote/upstreambranch.

Updated version attached.

Paolo



[-- Attachment #2: git-builtin-branch-config-2.patch --]
[-- Type: text/plain, Size: 7749 bytes --]

* git-branch: register where to merge from, when branching off a remote branch.

A rather standard (in 1.5) procedure for branching off a remote archive is:

  git checkout -b branchname remote/upstreambranch
  git config --add branch.branchname.remote remote
  git config --add branch.branchname.merge refs/heads/upstreambranch

In this case, we can save the user some effort if "git branch" (and
"git checkout -b") automatically do the two "git-config --add"s when the
source branch is remote.  There is a good chance that some user wants
to merge something different, but in that case they have to specify what
to merge _anyway_.

Dually, we remove the branch.branchname section when the user does
"git branch -d".


diff --git a/builtin-branch.c b/builtin-branch.c
index d0179b0..c1563cf 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -147,8 +147,16 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
 			error("Error deleting %sbranch '%s'", remote,
 			       argv[i]);
 			ret = 1;
-		} else
+		} else {
+			/* Remove git-config keys.  */
+			if (kinds == REF_LOCAL_BRANCH) {
+				char *config_key = xmalloc(strlen(argv[i]) + 8);
+				sprintf(config_key, "branch.%s", argv[i]);
+				git_config_remove_section(config_key);
+			}
+
 			printf("Deleted %sbranch %s.\n", remote, argv[i]);
+		}
 
 	}
 
@@ -308,6 +316,27 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
 	free_ref_list(&ref_list);
 }
 
+static void register_branch_pull (const char *name, const char *remote_name)
+{
+	char *slash = strchr(remote_name, '/');
+
+	char *config_key = xmalloc(strlen(name) + 15);
+	char *merge_value = xmalloc(strlen(remote_name) + 10);
+
+	char *remote_value = xstrdup(remote_name);
+	remote_value[slash - remote_name] = 0;
+	sprintf(config_key, "branch.%s.remote", name);
+	git_config_set(config_key, remote_value);
+
+	sprintf(merge_value, "refs/heads/%s", slash + 1);
+	sprintf(config_key, "branch.%s.merge", name);
+	git_config_set(config_key, merge_value);
+
+	free (config_key);
+	free (remote_value);
+	free (merge_value);
+}
+
 static void create_branch(const char *name, const char *start_name,
 			  unsigned char *start_sha1,
 			  int force, int reflog)
@@ -315,8 +344,8 @@ static void create_branch(const char *name, const char *start_name,
 	struct ref_lock *lock;
 	struct commit *commit;
 	unsigned char sha1[20];
-	char ref[PATH_MAX], msg[PATH_MAX + 20];
-	int forcing = 0;
+	char *real_ref = NULL, ref[PATH_MAX], msg[PATH_MAX + 20];
+	int forcing = 0, remote = 0;
 
 	snprintf(ref, sizeof ref, "refs/heads/%s", name);
 	if (check_ref_format(ref))
@@ -333,7 +362,9 @@ static void create_branch(const char *name, const char *start_name,
 	if (start_sha1)
 		/* detached HEAD */
 		hashcpy(sha1, start_sha1);
-	else if (get_sha1(start_name, sha1))
+	else if (dwim_ref(start_name, strlen (start_name), sha1, &real_ref))
+		remote = !prefixcmp(real_ref, "refs/remotes/");
+	else
 		die("Not a valid object name: '%s'.", start_name);
 
 	if ((commit = lookup_commit_reference(sha1)) == NULL)
@@ -354,8 +385,16 @@ static void create_branch(const char *name, const char *start_name,
 		snprintf(msg, sizeof msg, "branch: Created from %s",
 			 start_name);
 
+	/* When branching off a remote branch, set up so that git-pull
+	   automatically merges from there.  */
+	if (remote)
+		register_branch_pull (name, real_ref + 13);
+
 	if (write_ref_sha1(lock, sha1, msg) < 0)
 		die("Failed to write ref: %s.", strerror(errno));
+
+	if (real_ref)
+		free (real_ref);
 }
 
 static void rename_branch(const char *oldname, const char *newname, int force)
diff --git a/cache.h b/cache.h
index 8bbc142..797483b 100644
--- a/cache.h
+++ b/cache.h
@@ -438,6 +438,7 @@ extern int git_config_bool(const char *, const char *);
 extern int git_config_set(const char *, const char *);
 extern int git_config_set_multivar(const char *, const char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
+extern int git_config_remove_section(const char *);
 extern int check_repository_format_version(const char *var, const char *value);
 
 #define MAX_GITNAME (1000)
diff --git a/config.c b/config.c
index 0ff413b..acd83aa 100644
--- a/config.c
+++ b/config.c
@@ -854,6 +854,33 @@ write_err_out:
 
 }
 
+static int section_name_match (const char *buf, const char *name)
+{
+	int i = 0, j = 0, dot = 0;
+	for (; buf[i] && buf[i] != ']'; i++) {
+		if (!dot && isspace(buf[i])) {
+			dot = 1;
+			if (name[j++] != '.')
+				break;
+			for (i++; isspace(buf[i]); i++)
+				; /* do nothing */
+			if (buf[i] != '"')
+				break;
+			continue;
+		}
+		if (buf[i] == '\\' && dot)
+			i++;
+		else if (buf[i] == '"' && dot) {
+			for (i++; isspace(buf[i]); i++)
+				; /* do_nothing */
+			break;
+		}
+		if (buf[i] != name[j++])
+			break;
+	}
+	return (buf[i] == ']' && name[j] == 0);
+}
+
 int git_config_rename_section(const char *old_name, const char *new_name)
 {
 	int ret = 0;
@@ -885,40 +912,15 @@ int git_config_rename_section(const char *old_name, const char *new_name)
 		int length;
 		for (i = 0; buf[i] && isspace(buf[i]); i++)
 			; /* do nothing */
-		if (buf[i] == '[') {
+		if (buf[i] == '[' && section_name_match (&buf[i+1], old_name)) {
 			/* it's a section */
-			int j = 0, dot = 0;
-			for (i++; buf[i] && buf[i] != ']'; i++) {
-				if (!dot && isspace(buf[i])) {
-					dot = 1;
-					if (old_name[j++] != '.')
-						break;
-					for (i++; isspace(buf[i]); i++)
-						; /* do nothing */
-					if (buf[i] != '"')
-						break;
-					continue;
-				}
-				if (buf[i] == '\\' && dot)
-					i++;
-				else if (buf[i] == '"' && dot) {
-					for (i++; isspace(buf[i]); i++)
-						; /* do_nothing */
-					break;
-				}
-				if (buf[i] != old_name[j++])
-					break;
-			}
-			if (buf[i] == ']' && old_name[j] == 0) {
-				/* old_name matches */
-				ret++;
-				store.baselen = strlen(new_name);
-				if (!store_write_section(out_fd, new_name)) {
-					ret = write_error();
-					goto out;
-				}
-				continue;
+			ret++;
+			store.baselen = strlen(new_name);
+			if (!store_write_section(out_fd, new_name)) {
+				ret = write_error();
+				goto out;
 			}
+			continue;
 		}
 		length = strlen(buf);
 		if (write_in_full(out_fd, buf, length) != length) {
@@ -934,3 +936,58 @@ int git_config_rename_section(const char *old_name, const char *new_name)
 	return ret;
 }
 
+int git_config_remove_section(const char *name)
+{
+	int ret = 0;
+	char *config_filename;
+	struct lock_file *lock = xcalloc(sizeof(struct lock_file), 1);
+	int out_fd;
+	int removing = 0;
+	char buf[1024];
+
+	config_filename = getenv(CONFIG_ENVIRONMENT);
+	if (!config_filename) {
+		config_filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
+		if (!config_filename)
+			config_filename  = git_path("config");
+	}
+	config_filename = xstrdup(config_filename);
+	out_fd = hold_lock_file_for_update(lock, config_filename, 0);
+	if (out_fd < 0) {
+		ret = error("Could not lock config file!");
+		goto out;
+	}
+
+	if (!(config_file = fopen(config_filename, "rb"))) {
+		ret = error("Could not open config file!");
+		goto out;
+	}
+
+	while (fgets(buf, sizeof(buf), config_file)) {
+		int i;
+		int length;
+		for (i = 0; buf[i] && isspace(buf[i]); i++)
+			; /* do nothing */
+		if (buf[i] == '[') {
+			if (section_name_match (&buf[i + 1], name)) {
+				/* name matches */
+				ret++;
+				removing = 1;
+			} else
+				removing = 0;
+		}
+		if (removing)
+			continue;
+		length = strlen(buf);
+		if (write_in_full(out_fd, buf, length) != length) {
+			ret = write_error();
+			goto out;
+		}
+	}
+	fclose(config_file);
+	if (close(out_fd) || commit_lock_file(lock) < 0)
+			ret = error("Cannot commit config file!");
+ out:
+	free(config_filename);
+	return ret;
+}



^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  1:25             ` Johannes Schindelin
@ 2007-03-01  7:55               ` Alex Riesen
  2007-03-01  8:02                 ` Paolo Bonzini
  0 siblings, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-03-01  7:55 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Paolo Bonzini, Julian Phillips, Andy Parkins, git, Paolo Bonzini

On 3/1/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>
> > Well, I find it unobvious for pull to magically starting merging.
>
> Pull is _all_ about merging.
>

... from what the user _conciously_ meant it to.

> > Perhaps I'm using branch configuration in .git/config for too long, and
> > actually expect nothing to be merged if there is no appropriate branch
> > configuration.
>
> It is not possible that you use that feature you described for too long,
> since it was not there in 1.4.x. There, whenever you said "git pull", it

the syntax was introduced about half a year ago. Plenty of time
to get used to it

> would try to blindly pull the default branch of the remote "origin", which
> might have been correct for the default branch (i.e. the branch
> automatically set up by git-clone), but not necessarily for the other
> branches.

which everyone hated. With this change it will not that blindly,
but still unexpectedly jump to some remote branch.

> However, with the proposed behaviour, more new users would get less "Huh?"
> experiences.

yes, it will be the old users who'd get the experiences. What do they
do, edit out unwanted tracking from .git/config everytime a branch
from remote is created?

Besides, I'm was just asking about providing an option (command-line
parameter) to change the behavior to what it was before!
Just "--no-tracking"?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  7:55               ` Alex Riesen
@ 2007-03-01  8:02                 ` Paolo Bonzini
  2007-03-01  8:10                   ` Alex Riesen
  0 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01  8:02 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git


 > which everyone hated. With this change it will not that blindly,
 > but still unexpectedly jump to some remote branch.
 >
 >> However, with the proposed behaviour, more new users would get less
 >> "Huh?" experiences.
 >
 > yes, it will be the old users who'd get the experiences. What do they
 > do, edit out unwanted tracking from .git/config everytime a branch
 > from remote is created?

If everyone hated the old behavior, old users should already be careful 
about not git-pull'ing (without options) from any branch but master.  So 
they won't see any difference.

Coming from arch, which is not really a masterpiece of intuitiveness, 
this detail (as well as others for which I may try writing patches 
later) struck me as *extremely* unintuitive...

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:02                 ` Paolo Bonzini
@ 2007-03-01  8:10                   ` Alex Riesen
  2007-03-01  8:18                     ` Junio C Hamano
  2007-03-01  8:29                     ` Paolo Bonzini
  0 siblings, 2 replies; 48+ messages in thread
From: Alex Riesen @ 2007-03-01  8:10 UTC (permalink / raw)
  To: bonzini; +Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git

On 3/1/07, Paolo Bonzini <paolo.bonzini@gmail.com> wrote:
>
>  > which everyone hated. With this change it will not that blindly,
>  > but still unexpectedly jump to some remote branch.
>  >
>  >> However, with the proposed behaviour, more new users would get less
>  >> "Huh?" experiences.
>  >
>  > yes, it will be the old users who'd get the experiences. What do they
>  > do, edit out unwanted tracking from .git/config everytime a branch
>  > from remote is created?
>
> If everyone hated the old behavior, old users should already be careful
> about not git-pull'ing (without options) from any branch but master.  So
> they won't see any difference.

except for .git/config growing uncontrollably

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:10                   ` Alex Riesen
@ 2007-03-01  8:18                     ` Junio C Hamano
  2007-03-02 15:53                       ` J. Bruce Fields
  2007-03-01  8:29                     ` Paolo Bonzini
  1 sibling, 1 reply; 48+ messages in thread
From: Junio C Hamano @ 2007-03-01  8:18 UTC (permalink / raw)
  To: Alex Riesen
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git

"Alex Riesen" <raa.lkml@gmail.com> writes:

>> If everyone hated the old behavior, old users should already be careful
>> about not git-pull'ing (without options) from any branch but master.  So
>> they won't see any difference.
>
> except for .git/config growing uncontrollably

I think this should be a new option, not the _modified default_.
Otherwise it would be harder to sell to olde timers.

	$ git checkout -B <newbranch> remotes/<blah>
        $ git branch --track <newbranch> remotes/<blah>

might be a good compromise.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:10                   ` Alex Riesen
  2007-03-01  8:18                     ` Junio C Hamano
@ 2007-03-01  8:29                     ` Paolo Bonzini
  2007-03-01  8:33                       ` Alex Riesen
  1 sibling, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01  8:29 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git


>> If everyone hated the old behavior, old users should already be careful
>> about not git-pull'ing (without options) from any branch but master.  So
>> they won't see any difference.
> 
> except for .git/config growing uncontrollably

While I am probably going to modify the patch to satisfy Junio, have you 
noticed that "git branch -d" will delete the section, hence .git/config 
will not be growing uncontrollably?

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:29                     ` Paolo Bonzini
@ 2007-03-01  8:33                       ` Alex Riesen
  2007-03-01  8:45                         ` Paolo Bonzini
  0 siblings, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-03-01  8:33 UTC (permalink / raw)
  To: bonzini; +Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git

On 3/1/07, Paolo Bonzini <paolo.bonzini@gmail.com> wrote:
>
> >> If everyone hated the old behavior, old users should already be careful
> >> about not git-pull'ing (without options) from any branch but master.  So
> >> they won't see any difference.
> >
> > except for .git/config growing uncontrollably
>
> While I am probably going to modify the patch to satisfy Junio, have you
> noticed that "git branch -d" will delete the section, hence .git/config
> will not be growing uncontrollably?
>

Maybe you also have noticed that it will remove also the reference?
How do I remove the garbage you added for TRACKING?!

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:33                       ` Alex Riesen
@ 2007-03-01  8:45                         ` Paolo Bonzini
  2007-03-01  8:59                           ` Alex Riesen
  0 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01  8:45 UTC (permalink / raw)
  To: Alex Riesen
  Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git, Junio C Hamano


>> While I am probably going to modify the patch to satisfy Junio, have you
>> noticed that "git branch -d" will delete the section, hence .git/config
>> will not be growing uncontrollably?
> 
> Maybe you also have noticed that it will remove also the reference?

Sure I have.

> How do I remove the garbage you added for TRACKING?!

I see two possibilities:

1) I can add a "git-config --remove-section" option.  So you can do 
"git-pull" to merge onto your branches, and then remove the tracking 
section.

2) I can add a "git-branch --stop-tracking" option, which just removes 
the section.

3) Same as 2), plus I add a "git-branch --no-track" option, which does 
not add the section in the first place.  But I do believe that there is 
no reason why this cannot be the default.

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:45                         ` Paolo Bonzini
@ 2007-03-01  8:59                           ` Alex Riesen
  2007-03-01  9:37                             ` [PATCH] defaults for where to merge from (take 3) Paolo Bonzini
  0 siblings, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-03-01  8:59 UTC (permalink / raw)
  To: bonzini
  Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git, Junio C Hamano

On 3/1/07, Paolo Bonzini <paolo.bonzini@gmail.com> wrote:
> > How do I remove the garbage you added for TRACKING?!
>
> I see two possibilities:
>
> 1) I can add a "git-config --remove-section" option.  So you can do
> "git-pull" to merge onto your branches, and then remove the tracking
> section.

This is irrelevant in this particular context. It is just wrong here:
are you sure you _CAN_ know what it is you are removing?
Git config syntax is loosely defined, and branch or remote sections
can have important user information. Which he does not immediately
see typing git config --remove-section branch.abc _JUST_ to get
rid of the configuration he did not want in first place!

> 2) I can add a "git-branch --stop-tracking" option, which just removes
> the section.

This is independent and _probably_ not really needed. It is also
probably more complex than you think. Consider:

[remote "abc"]
  url = ...
  fetch = refs/heads/*:refs/remotes/abc/*
  fetch = refs/heads/test:refs/heads/abc-test

> 3) Same as 2), plus I add a "git-branch --no-track" option, which does
> not add the section in the first place.  But I do believe that there is
> no reason why this cannot be the default.

This is just what I asked for except for the first part.
And I see no reason for it to _BE_ the default.
Actually, how about making the default configurable _AND_ have
the --no-track option (for scripting)?

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH] defaults for where to merge from (take 3)
  2007-03-01  8:59                           ` Alex Riesen
@ 2007-03-01  9:37                             ` Paolo Bonzini
  2007-03-01 10:12                               ` Alex Riesen
  0 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01  9:37 UTC (permalink / raw)
  To: Alex Riesen
  Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git, Junio C Hamano

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


> Actually, how about making the default configurable _AND_ have
> the --no-track option (for scripting)?

Fine by me.  And also --track in case you want to try it out.  ;-)

I made it default true, environment.c can be changed by Junio if he 
applies the patch.

Patch attached.  --remove-section will go in a separate patch.

Paolo

[-- Attachment #2: git-builtin-branch-config-3.patch --]
[-- Type: text/plain, Size: 7507 bytes --]

* git-branch: register where to merge from, when branching off a remote branch.

A rather standard (in 1.5) procedure for branching off a remote archive is:

  git checkout -b branchname remote/upstreambranch
  git config --add branch.branchname.remote remote
  git config --add branch.branchname.merge refs/heads/upstreambranch

In this case, we can save the user some effort if "git branch" (and
"git checkout -b") automatically do the two "git-config --add"s when the
source branch is remote.  There is a good chance that some user wants
to merge something different, but in that case they have to specify what
to merge _anyway_.

The behavior is controlled by core.trackremotebranches, and can be
fine-grained to a specific invocation of "git branch" using the new
--track and --no-track options.

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index aa1fdd4..14dc07d 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git-branch' [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]
-'git-branch' [-l] [-f] <branchname> [<start-point>]
+'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
 'git-branch' (-m | -M) [<oldbranch>] <newbranch>
 'git-branch' (-d | -D) [-r] <branchname>...
 
@@ -25,6 +25,12 @@ It will start out with a head equal to the one given as <start-point>.
 If no <start-point> is given, the branch will be created with a head
 equal to that of the currently checked out branch.
 
+When a local branch is started off a remote branch, git will setup
+the branch so that gitlink:git-pull[1] will appropriately merge from
+that remote branch.  If this behavior is undesired, it is possible
+to change it using the `core.trackremotebranches` option, or the
+`--track` and `--no-track` options.
+
 With a '-m' or '-M' option, <oldbranch> will be renamed to <newbranch>.
 If <oldbranch> had a corresponding reflog, it is renamed to match
 <newbranch>, and a reflog entry is created to remember the branch
diff --git a/builtin-branch.c b/builtin-branch.c
index d0179b0..20de049 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,7 +12,7 @@
 #include "builtin.h"
 
 static const char builtin_branch_usage[] =
-  "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
+  "git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
 
 #define REF_UNKNOWN_TYPE    0x00
 #define REF_LOCAL_BRANCH    0x01
@@ -308,15 +307,36 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
 	free_ref_list(&ref_list);
 }
 
+static void register_branch_pull (const char *name, const char *remote_name)
+{
+	char *slash = strchr(remote_name, '/');
+
+	char *config_key = xmalloc(strlen(name) + 15);
+	char *merge_value = xmalloc(strlen(remote_name) + 10);
+
+	char *remote_value = xstrdup(remote_name);
+	remote_value[slash - remote_name] = 0;
+	sprintf(config_key, "branch.%s.remote", name);
+	git_config_set(config_key, remote_value);
+
+	sprintf(merge_value, "refs/heads/%s", slash + 1);
+	sprintf(config_key, "branch.%s.merge", name);
+	git_config_set(config_key, merge_value);
+
+	free (config_key);
+	free (remote_value);
+	free (merge_value);
+}
+
 static void create_branch(const char *name, const char *start_name,
 			  unsigned char *start_sha1,
-			  int force, int reflog)
+			  int force, int reflog, int track)
 {
 	struct ref_lock *lock;
 	struct commit *commit;
 	unsigned char sha1[20];
-	char ref[PATH_MAX], msg[PATH_MAX + 20];
-	int forcing = 0;
+	char *real_ref = NULL, ref[PATH_MAX], msg[PATH_MAX + 20];
+	int forcing = 0, remote = 0;
 
 	snprintf(ref, sizeof ref, "refs/heads/%s", name);
 	if (check_ref_format(ref))
@@ -333,7 +353,9 @@ static void create_branch(const char *name, const char *start_name,
 	if (start_sha1)
 		/* detached HEAD */
 		hashcpy(sha1, start_sha1);
-	else if (get_sha1(start_name, sha1))
+	else if (dwim_ref(start_name, strlen (start_name), sha1, &real_ref))
+		remote = !prefixcmp(real_ref, "refs/remotes/");
+	else
 		die("Not a valid object name: '%s'.", start_name);
 
 	if ((commit = lookup_commit_reference(sha1)) == NULL)
@@ -354,8 +376,16 @@ static void create_branch(const char *name, const char *start_name,
 		snprintf(msg, sizeof msg, "branch: Created from %s",
 			 start_name);
 
+	/* When branching off a remote branch, set up so that git-pull
+	   automatically merges from there.  */
+	if (remote && track)
+		register_branch_pull (name, real_ref + 13);
+
 	if (write_ref_sha1(lock, sha1, msg) < 0)
 		die("Failed to write ref: %s.", strerror(errno));
+
+	if (real_ref)
+		free (real_ref);
 }
 
 static void rename_branch(const char *oldname, const char *newname, int force)
@@ -397,11 +427,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	int delete = 0, force_delete = 0, force_create = 0;
 	int rename = 0, force_rename = 0;
 	int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
-	int reflog = 0;
+	int reflog = 0, track;
 	int kinds = REF_LOCAL_BRANCH;
 	int i;
 
 	git_config(git_branch_config);
+	track = track_remote_branches;
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
@@ -412,6 +443,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			i++;
 			break;
 		}
+		if (!strcmp(arg, "--track")) {
+			track = 1;
+			continue;
+		}
+		if (!strcmp(arg, "--no-track")) {
+			track = 0;
+			continue;
+		}
 		if (!strcmp(arg, "-d")) {
 			delete = 1;
 			continue;
@@ -490,9 +529,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	else if (rename && (i == argc - 2))
 		rename_branch(argv[i], argv[i + 1], force_rename);
 	else if (i == argc - 1)
-		create_branch(argv[i], head, head_sha1, force_create, reflog);
+		create_branch(argv[i], head, head_sha1, force_create, reflog,
+			      track);
 	else if (i == argc - 2)
-		create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
+		create_branch(argv[i], argv[i+1], NULL, force_create, reflog,
+			      track);
 	else
 		usage(builtin_branch_usage);
 
diff --git a/cache.h b/cache.h
index 8bbc142..585a9b4 100644
--- a/cache.h
+++ b/cache.h
@@ -205,6 +205,7 @@ extern int trust_executable_bit;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
 extern int log_all_ref_updates;
+extern int track_remote_branches;
 extern int warn_ambiguous_refs;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
diff --git a/config.c b/config.c
index 0ff413b..49df7bd 100644
--- a/config.c
+++ b/config.c
@@ -294,6 +294,11 @@ int git_default_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.trackremotebranches")) {
+		track_remote_branches = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "core.legacyheaders")) {
 		use_legacy_headers = git_config_bool(var, value);
 		return 0;
diff --git a/environment.c b/environment.c
index 570e32a..e440d05 100644
--- a/environment.c
+++ b/environment.c
@@ -17,6 +17,7 @@ int assume_unchanged;
 int prefer_symlink_refs;
 int is_bare_repository_cfg = -1; /* unspecified */
 int log_all_ref_updates = -1; /* unspecified */
+int track_remote_branches = 1;
 int warn_ambiguous_refs = 1;
 int repository_format_version;
 char *git_commit_encoding;

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-01  9:37                             ` [PATCH] defaults for where to merge from (take 3) Paolo Bonzini
@ 2007-03-01 10:12                               ` Alex Riesen
  2007-03-01 10:17                                 ` Paolo Bonzini
  2007-03-01 10:27                                 ` Junio C Hamano
  0 siblings, 2 replies; 48+ messages in thread
From: Alex Riesen @ 2007-03-01 10:12 UTC (permalink / raw)
  To: bonzini
  Cc: Johannes Schindelin, Julian Phillips, Andy Parkins, git, Junio C Hamano

On 3/1/07, Paolo Bonzini <paolo.bonzini@gmail.com> wrote:
> > Actually, how about making the default configurable _AND_ have
> > the --no-track option (for scripting)?
>
> Fine by me.  And also --track in case you want to try it out.  ;-)
>

Ack. Thanks!

> Patch attached.  --remove-section will go in a separate patch.

Still think it is a very dangerous operation.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-01 10:12                               ` Alex Riesen
@ 2007-03-01 10:17                                 ` Paolo Bonzini
  2007-03-01 10:27                                 ` Junio C Hamano
  1 sibling, 0 replies; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01 10:17 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git


>> Patch attached.  --remove-section will go in a separate patch.
> 
> Still think it is a very dangerous operation.

Agreed, that's why I put it in git-config.

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-01 10:12                               ` Alex Riesen
  2007-03-01 10:17                                 ` Paolo Bonzini
@ 2007-03-01 10:27                                 ` Junio C Hamano
  2007-03-01 10:42                                   ` Alex Riesen
                                                     ` (2 more replies)
  1 sibling, 3 replies; 48+ messages in thread
From: Junio C Hamano @ 2007-03-01 10:27 UTC (permalink / raw)
  To: Alex Riesen
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git,
	Junio C Hamano

"Alex Riesen" <raa.lkml@gmail.com> writes:

> On 3/1/07, Paolo Bonzini <paolo.bonzini@gmail.com> wrote:
>> > Actually, how about making the default configurable _AND_ have
>> > the --no-track option (for scripting)?
>>
>> Fine by me.  And also --track in case you want to try it out.  ;-)
>
> Ack. Thanks!

Having both --track and --no-track options is a nice touch to
give scripts dependable behaviour.  Well done.

>> Patch attached.  --remove-section will go in a separate patch.
>
> Still think it is a very dangerous operation.

I am going to bed now, but I would appreciate if the list could
help Paolo:

 (1) with styles.  I have only given a cursory look at the
     patch, but I think people already know what I like and not
     like.

 (2) by reviewing the changes to the .config writer.  That
     traditionally has been one of the more fragile parts of the
     system, and I am reluctant to look at it.

 (3) come up with a version that is easier-to-apply (including
     sending an in-line patch).

I would just feel better to see a patch like this, which is a
significant improvement to the system, to be properly signed-off
by the submitter.

Also it would be nice if you guys can fight it out about the
default value for 'tracked'.  I do not think _I_ can defend the
position to create these tracking configurations by default to
old timers (especially the ones that do not follow the git
mailing list), as I am not convinced (not yet, anyway).

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-01 10:27                                 ` Junio C Hamano
@ 2007-03-01 10:42                                   ` Alex Riesen
  2007-03-02  4:49                                     ` Junio C Hamano
  2007-03-01 10:47                                   ` Alex Riesen
  2007-03-01 16:33                                   ` [PATCH] defaults for where to merge from (take 3, inline) Paolo Bonzini
  2 siblings, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-03-01 10:42 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git

On 3/1/07, Junio C Hamano <junkio@cox.net> wrote:
> Also it would be nice if you guys can fight it out about the
> default value for 'tracked'.  I do not think _I_ can defend the
> position to create these tracking configurations by default to
> old timers (especially the ones that do not follow the git
> mailing list), as I am not convinced (not yet, anyway).

I agree with Dscho wrt the default, partly because I don't
care as long as I can change it, partly because the learning
curve curve can never be shallow enough and the less
surprises the better.
The oldtimers will have no problems changing the default,
and the option is properly documented in the patch.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-01 10:27                                 ` Junio C Hamano
  2007-03-01 10:42                                   ` Alex Riesen
@ 2007-03-01 10:47                                   ` Alex Riesen
  2007-03-01 16:33                                   ` [PATCH] defaults for where to merge from (take 3, inline) Paolo Bonzini
  2 siblings, 0 replies; 48+ messages in thread
From: Alex Riesen @ 2007-03-01 10:47 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git

On 3/1/07, Junio C Hamano <junkio@cox.net> wrote:
> Also it would be nice if you guys can fight it out about the
> default value for 'tracked'.  I do not think _I_ can defend the
> position to create these tracking configurations by default to
> old timers (especially the ones that do not follow the git
> mailing list), as I am not convinced (not yet, anyway).

BTW, how about printing a message that the newly created
branch is a tracker of that remote branch?

  $ git branch abc origin/master
  Branch "abc" tracks "remotes/origin/master"
  $ _

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3, inline)
  2007-03-01 10:27                                 ` Junio C Hamano
  2007-03-01 10:42                                   ` Alex Riesen
  2007-03-01 10:47                                   ` Alex Riesen
@ 2007-03-01 16:33                                   ` Paolo Bonzini
  2007-03-01 22:01                                     ` Johannes Schindelin
  2 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-01 16:33 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Alex Riesen, Johannes Schindelin, Julian Phillips, Andy Parkins, git

>  (2) by reviewing the changes to the .config writer.  That
>      traditionally has been one of the more fragile parts of the
>      system, and I am reluctant to look at it.

Just FYI, this was broken into a separate patch.

> I would just feel better to see a patch like this, which is a
> significant improvement to the system, to be properly signed-off
> by the submitter.

I hope this is better, I tried to follow the steps in
SubmittingPatches properly.  The code is actually the same
as take 3.


* git-branch: register where to merge from, when branching off a remote branch.

A rather standard (in 1.5) procedure for branching off a remote archive is:

  git checkout -b branchname remote/upstreambranch
  git config --add branch.branchname.remote remote
  git config --add branch.branchname.merge refs/heads/upstreambranch

In this case, we can save the user some effort if "git branch" (and
"git checkout -b") automatically do the two "git-config --add"s when the
source branch is remote.  There is a good chance that some user wants
to merge something different, but in that case they have to specify what
to merge _anyway_.

The behavior is controlled by core.trackremotebranches, and can be
fine-grained to a specific invocation of "git branch" using the new
--track and --no-track options.

Signed-off-by: Paolo Bonzini  <bonzini@gnu.org>
---
 Documentation/git-branch.txt |    8 +++++
 builtin-branch.c             |   58 +++++++++++++++++++++++++++++++++++++------
 cache.h                      |    1 
 config.c                     |    5 +++
 environment.c                |    1 
 5 files changed, 64 insertions(+), 9 deletions(-)


diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index aa1fdd4..14dc07d 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git-branch' [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]
-'git-branch' [-l] [-f] <branchname> [<start-point>]
+'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
 'git-branch' (-m | -M) [<oldbranch>] <newbranch>
 'git-branch' (-d | -D) [-r] <branchname>...
 
@@ -25,6 +25,12 @@ It will start out with a head equal to the one given as <start-point>.
 If no <start-point> is given, the branch will be created with a head
 equal to that of the currently checked out branch.
 
+When a local branch is started off a remote branch, git will setup
+the branch so that gitlink:git-pull[1] will appropriately merge from
+that remote branch.  If this behavior is undesired, it is possible
+to change it using the `core.trackremotebranches` option, or the
+`--track` and `--no-track` options.
+
 With a '-m' or '-M' option, <oldbranch> will be renamed to <newbranch>.
 If <oldbranch> had a corresponding reflog, it is renamed to match
 <newbranch>, and a reflog entry is created to remember the branch
diff --git a/builtin-branch.c b/builtin-branch.c
index d0179b0..20de049 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,7 +12,7 @@
 #include "builtin.h"
 
 static const char builtin_branch_usage[] =
-  "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
+  "git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
 
 #define REF_UNKNOWN_TYPE    0x00
 #define REF_LOCAL_BRANCH    0x01
@@ -308,15 +307,36 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
 	free_ref_list(&ref_list);
 }
 
+static void register_branch_pull (const char *name, const char *remote_name)
+{
+	char *slash = strchr(remote_name, '/');
+
+	char *config_key = xmalloc(strlen(name) + 15);
+	char *merge_value = xmalloc(strlen(remote_name) + 10);
+
+	char *remote_value = xstrdup(remote_name);
+	remote_value[slash - remote_name] = 0;
+	sprintf(config_key, "branch.%s.remote", name);
+	git_config_set(config_key, remote_value);
+
+	sprintf(merge_value, "refs/heads/%s", slash + 1);
+	sprintf(config_key, "branch.%s.merge", name);
+	git_config_set(config_key, merge_value);
+
+	free (config_key);
+	free (remote_value);
+	free (merge_value);
+}
+
 static void create_branch(const char *name, const char *start_name,
 			  unsigned char *start_sha1,
-			  int force, int reflog)
+			  int force, int reflog, int track)
 {
 	struct ref_lock *lock;
 	struct commit *commit;
 	unsigned char sha1[20];
-	char ref[PATH_MAX], msg[PATH_MAX + 20];
-	int forcing = 0;
+	char *real_ref = NULL, ref[PATH_MAX], msg[PATH_MAX + 20];
+	int forcing = 0, remote = 0;
 
 	snprintf(ref, sizeof ref, "refs/heads/%s", name);
 	if (check_ref_format(ref))
@@ -333,7 +353,9 @@ static void create_branch(const char *name, const char *start_name,
 	if (start_sha1)
 		/* detached HEAD */
 		hashcpy(sha1, start_sha1);
-	else if (get_sha1(start_name, sha1))
+	else if (dwim_ref(start_name, strlen (start_name), sha1, &real_ref))
+		remote = !prefixcmp(real_ref, "refs/remotes/");
+	else
 		die("Not a valid object name: '%s'.", start_name);
 
 	if ((commit = lookup_commit_reference(sha1)) == NULL)
@@ -354,8 +376,16 @@ static void create_branch(const char *name, const char *start_name,
 		snprintf(msg, sizeof msg, "branch: Created from %s",
 			 start_name);
 
+	/* When branching off a remote branch, set up so that git-pull
+	   automatically merges from there.  */
+	if (remote && track)
+		register_branch_pull (name, real_ref + 13);
+
 	if (write_ref_sha1(lock, sha1, msg) < 0)
 		die("Failed to write ref: %s.", strerror(errno));
+
+	if (real_ref)
+		free (real_ref);
 }
 
 static void rename_branch(const char *oldname, const char *newname, int force)
@@ -397,11 +427,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	int delete = 0, force_delete = 0, force_create = 0;
 	int rename = 0, force_rename = 0;
 	int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
-	int reflog = 0;
+	int reflog = 0, track;
 	int kinds = REF_LOCAL_BRANCH;
 	int i;
 
 	git_config(git_branch_config);
+	track = track_remote_branches;
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
@@ -412,6 +443,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			i++;
 			break;
 		}
+		if (!strcmp(arg, "--track")) {
+			track = 1;
+			continue;
+		}
+		if (!strcmp(arg, "--no-track")) {
+			track = 0;
+			continue;
+		}
 		if (!strcmp(arg, "-d")) {
 			delete = 1;
 			continue;
@@ -490,9 +529,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	else if (rename && (i == argc - 2))
 		rename_branch(argv[i], argv[i + 1], force_rename);
 	else if (i == argc - 1)
-		create_branch(argv[i], head, head_sha1, force_create, reflog);
+		create_branch(argv[i], head, head_sha1, force_create, reflog,
+			      track);
 	else if (i == argc - 2)
-		create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
+		create_branch(argv[i], argv[i+1], NULL, force_create, reflog,
+			      track);
 	else
 		usage(builtin_branch_usage);
 
diff --git a/cache.h b/cache.h
index 8bbc142..585a9b4 100644
--- a/cache.h
+++ b/cache.h
@@ -205,6 +205,7 @@ extern int trust_executable_bit;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
 extern int log_all_ref_updates;
+extern int track_remote_branches;
 extern int warn_ambiguous_refs;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
diff --git a/config.c b/config.c
index 0ff413b..49df7bd 100644
--- a/config.c
+++ b/config.c
@@ -294,6 +294,11 @@ int git_default_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.trackremotebranches")) {
+		track_remote_branches = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "core.legacyheaders")) {
 		use_legacy_headers = git_config_bool(var, value);
 		return 0;
diff --git a/environment.c b/environment.c
index 570e32a..e440d05 100644
--- a/environment.c
+++ b/environment.c
@@ -17,6 +17,7 @@ int assume_unchanged;
 int prefer_symlink_refs;
 int is_bare_repository_cfg = -1; /* unspecified */
 int log_all_ref_updates = -1; /* unspecified */
+int track_remote_branches = 1;
 int warn_ambiguous_refs = 1;
 int repository_format_version;
 char *git_commit_encoding;

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3, inline)
  2007-03-01 16:33                                   ` [PATCH] defaults for where to merge from (take 3, inline) Paolo Bonzini
@ 2007-03-01 22:01                                     ` Johannes Schindelin
  2007-03-02  8:10                                       ` Paolo Bonzini
  2007-03-02 14:10                                       ` Jakub Narebski
  0 siblings, 2 replies; 48+ messages in thread
From: Johannes Schindelin @ 2007-03-01 22:01 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Junio C Hamano, Alex Riesen, Julian Phillips, Andy Parkins, git

Hi,

please don't take my comments as insults or even strict rules. It is 
purely for your consideration. (I say this because I haven't seen you so 
often on this list, so you might not know that discussions about patches 
are sometimes, erm, lively...)

On Thu, 1 Mar 2007, Paolo Bonzini wrote:

> >  (2) by reviewing the changes to the .config writer.  That
> >      traditionally has been one of the more fragile parts of the
> >      system, and I am reluctant to look at it.
> 
> Just FYI, this was broken into a separate patch.
> 
> > I would just feel better to see a patch like this, which is a
> > significant improvement to the system, to be properly signed-off
> > by the submitter.
> 
> I hope this is better, I tried to follow the steps in
> SubmittingPatches properly.  The code is actually the same
> as take 3.

According to SubmittingPatches, this is a cover letter.

	You often want to add additional explanation about the patch, 
	other than the commit message itself.  Place such "cover letter" 
	material between the three dash lines and the diffstat.

So, please put it after the three dashes and the diffstat next time.

> * git-branch: register where to merge from, when branching off a remote branch.

This is the oneline description, which should have been the Subject of the 
mail, preferably prefixed by "[PATCH]" to make it obvious that it is not 
yet another reply in a medium-sized thread, but actually a code 
contribution. SubmittingPatches is not clear about this: you can write 
_anything_ in brackets, and it will be stripped from the commit message 
automatically. In your case, I would have preferred "[PATCH, 3rd 
version]".

> A rather standard (in 1.5) procedure for branching off a remote archive is:

Since this will go into the commit message, which is usually shown in the 
output of "git log", indented, it would be nice to break lines early.

Again, I think that SubmittingPatches is not totally clear about this: I 
try to maintain a maximum width of 76 characters (which seems to be the 
default with pine -- my mail program -- anyway).

> The behavior is controlled by core.trackremotebranches,

I'd make it obvious here that it is on by default -- even if you state 
that earlier, too.

[I leave comments on documentation to others, since I cannot write them 
myself.]

> diff --git a/builtin-branch.c b/builtin-branch.c
> index d0179b0..20de049 100644
> --- a/builtin-branch.c
> +++ b/builtin-branch.c
> @@ -12,7 +12,7 @@
>  #include "builtin.h"
>  
>  static const char builtin_branch_usage[] =
> -  "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
> +  "git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
>  
>  #define REF_UNKNOWN_TYPE    0x00
>  #define REF_LOCAL_BRANCH    0x01
> @@ -308,15 +307,36 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
>  	free_ref_list(&ref_list);
>  }
>  
> +static void register_branch_pull (const char *name, const char *remote_name)

It is not yet remote_name, right? it is branch_name. You extract the 
remote_name by finding the first slash.

> +{
> +	char *slash = strchr(remote_name, '/');
> +
> +	char *config_key = xmalloc(strlen(name) + 15);
> +	char *merge_value = xmalloc(strlen(remote_name) + 10);
> +
> +	char *remote_value = xstrdup(remote_name);

I'd use "char key[1024], value[1024]" instead, erroring out if one of the 
buffers are too small. It's not like you have to be memory efficient, and 
it is easier to read.

> +	remote_value[slash - remote_name] = 0;

You should check if slash == NULL and error out before using it.

> +	sprintf(config_key, "branch.%s.remote", name);

This would be a snprintf(key, sizeof(key), "branch.%s.remote", name); and 
snprintf(value, sizeof(value), "%.*s", slash - branch_name, branch_name);

> +	git_config_set(config_key, remote_value);
> +
> +	sprintf(merge_value, "refs/heads/%s", slash + 1);
> +	sprintf(config_key, "branch.%s.merge", name);
> +	git_config_set(config_key, merge_value);
> +
> +	free (config_key);
> +	free (remote_value);
> +	free (merge_value);
> +}
> +
>  static void create_branch(const char *name, const char *start_name,
>  			  unsigned char *start_sha1,
> -			  int force, int reflog)
> +			  int force, int reflog, int track)
>  {
>  	struct ref_lock *lock;
>  	struct commit *commit;
>  	unsigned char sha1[20];
> -	char ref[PATH_MAX], msg[PATH_MAX + 20];
> -	int forcing = 0;
> +	char *real_ref = NULL, ref[PATH_MAX], msg[PATH_MAX + 20];
> +	int forcing = 0, remote = 0;
>  
>  	snprintf(ref, sizeof ref, "refs/heads/%s", name);
>  	if (check_ref_format(ref))
> @@ -333,7 +353,9 @@ static void create_branch(const char *name, const char *start_name,
>  	if (start_sha1)
>  		/* detached HEAD */
>  		hashcpy(sha1, start_sha1);
> -	else if (get_sha1(start_name, sha1))
> +	else if (dwim_ref(start_name, strlen (start_name), sha1, &real_ref))
> +		remote = !prefixcmp(real_ref, "refs/remotes/");
> +	else
>  		die("Not a valid object name: '%s'.", start_name);

Yes, that is how I imagined it. The rest of your patch looks perfect to 
me.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-01 10:42                                   ` Alex Riesen
@ 2007-03-02  4:49                                     ` Junio C Hamano
  2007-03-02  9:05                                       ` Alex Riesen
  0 siblings, 1 reply; 48+ messages in thread
From: Junio C Hamano @ 2007-03-02  4:49 UTC (permalink / raw)
  To: Alex Riesen
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git

"Alex Riesen" <raa.lkml@gmail.com> writes:

> The oldtimers will have no problems changing the default,
> and the option is properly documented in the patch.

"Old-timers will have no problems" is not a good enough
justification to change the default.  You need to justify _why_
it is _they_ who needs to do the extra configuration.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3, inline)
  2007-03-01 22:01                                     ` Johannes Schindelin
@ 2007-03-02  8:10                                       ` Paolo Bonzini
  2007-03-02  8:50                                         ` [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch Paolo Bonzini
  2007-03-02 11:19                                         ` [PATCH] defaults for where to merge from (take 3, inline) Johannes Schindelin
  2007-03-02 14:10                                       ` Jakub Narebski
  1 sibling, 2 replies; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-02  8:10 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git


> please don't take my comments as insults or even strict rules. It is 
> purely for your consideration. (I say this because I haven't seen you so 
> often on this list, so you might not know that discussions about patches 
> are sometimes, erm, lively...)

I absolutely haven't taken any of these comments in the thread as insults (the only thing I found a little dubious, was some usage of uppercase), and I got a lot of constructive criticism that outweighed the "lively" tone.  And as a mistake on my part, I probably should have lurked a bit longer than I did.

>> +static void register_branch_pull (const char *name, const char *remote_name)
> 
> It is not yet remote_name, right? it is branch_name. You extract the 
> remote_name by finding the first slash.

Yeah, it's a remote_branch_name in fact.

> I'd use "char key[1024], value[1024]" instead, erroring out if one of the 
> buffers are too small. It's not like you have to be memory efficient, and 
> it is easier to read.

Ok.

>> +	remote_value[slash - remote_name] = 0;
> 
> You should check if slash == NULL and error out before using it.

remote_name is of the form "REMOTE/BRANCH", because it comes from dwim_ref's output after stripping "refs/remotes/" from the beginning.

> Yes, that is how I imagined it. The rest of your patch looks perfect to 
> me.

I will submit again with the requested changes.  I guess the body of this message is too long to become a "cover letter".

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02  8:10                                       ` Paolo Bonzini
@ 2007-03-02  8:50                                         ` Paolo Bonzini
  2007-03-02  9:52                                           ` Junio C Hamano
  2007-03-02 11:19                                         ` [PATCH] defaults for where to merge from (take 3, inline) Johannes Schindelin
  1 sibling, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-02  8:50 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Johannes Schindelin, Junio C Hamano, git

A rather standard (in 1.5) procedure for branching off a remote archive
is:

  git checkout -b branchname remote/upstreambranch
  git config --add branch.branchname.remote remote
  git config --add branch.branchname.merge refs/heads/upstreambranch

In this case, we can save the user some effort if "git branch" (and
"git checkout -b") automatically do the two "git-config --add"s when the
source branch is remote.  There is a good chance that some user wants
to merge something different, but in that case they have to specify what
to merge _anyway_.

The behavior is controlled by core.trackremotebranches (off by default;
subject to review later), and can be fine-grained to a specific invocation
of "git branch" using the new --track and --no-track options.

Signed-off-by: Paolo Bonzini  <bonzini@gnu.org>
---
 Documentation/git-branch.txt |    9 ++++++
 builtin-branch.c             |   56 ++++++++++++++++++++++++++++++++++++-------
 cache.h                      |    1 
 config.c                     |    5 +++
 environment.c                |    1 
 5 files changed, 63 insertions(+), 9 deletions(-)

	Includes comments by Johannes Schindelin on not using xmalloc for
	buffers, and better variable names.  Default is "false" in this
	version, unlike previous versions.

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index aa1fdd4..4ccbb3c 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git-branch' [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]
-'git-branch' [-l] [-f] <branchname> [<start-point>]
+'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
 'git-branch' (-m | -M) [<oldbranch>] <newbranch>
 'git-branch' (-d | -D) [-r] <branchname>...
 
@@ -25,6 +25,13 @@ It will start out with a head equal to the one given as <start-point>.
 If no <start-point> is given, the branch will be created with a head
 equal to that of the currently checked out branch.
 
+When a local branch is started off a remote branch, git can setup
+the branch so that gitlink:git-pull[1] will appropriately merge from
+that remote branch.  If this behavior is desired, it is possible
+to make it the default using the `core.trackremotebranches` option.
+Otherwise, it can be chosen per-branch using the `--track` and
+`--no-track` options.
+
 With a '-m' or '-M' option, <oldbranch> will be renamed to <newbranch>.
 If <oldbranch> had a corresponding reflog, it is renamed to match
 <newbranch>, and a reflog entry is created to remember the branch
diff --git a/builtin-branch.c b/builtin-branch.c
index d0179b0..96658ff 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,7 +12,7 @@
 #include "builtin.h"
 
 static const char builtin_branch_usage[] =
-  "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
+  "git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
 
 #define REF_UNKNOWN_TYPE    0x00
 #define REF_LOCAL_BRANCH    0x01
@@ -308,15 +308,34 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
 	free_ref_list(&ref_list);
 }
 
+static void register_pull (const char *name, const char *remote_branch_name)
+{
+	char *slash = strchr(remote_branch_name, '/');
+	char key[1024], value[1024];
+
+	if (strlen(remote_branch_name) >= 1024 - 11
+	    || strlen(name) >= 1024 - 15)
+		die ("what a long branch name you have!");
+
+	snprintf(key, sizeof(key), "branch.%s.remote", name);
+	snprintf(value, sizeof(value), "%.*s", slash - remote_branch_name,
+		 remote_branch_name);
+	git_config_set(key, value);
+
+	snprintf(key, sizeof(key), "branch.%s.merge", name);
+	snprintf(value, sizeof(value), "refs/heads/%s", slash + 1);
+	git_config_set(key, value);
+}
+
 static void create_branch(const char *name, const char *start_name,
 			  unsigned char *start_sha1,
-			  int force, int reflog)
+			  int force, int reflog, int track)
 {
 	struct ref_lock *lock;
 	struct commit *commit;
 	unsigned char sha1[20];
-	char ref[PATH_MAX], msg[PATH_MAX + 20];
-	int forcing = 0;
+	char *real_ref = NULL, ref[PATH_MAX], msg[PATH_MAX + 20];
+	int forcing = 0, remote = 0;
 
 	snprintf(ref, sizeof ref, "refs/heads/%s", name);
 	if (check_ref_format(ref))
@@ -333,7 +354,9 @@ static void create_branch(const char *name, const char *start_name,
 	if (start_sha1)
 		/* detached HEAD */
 		hashcpy(sha1, start_sha1);
-	else if (get_sha1(start_name, sha1))
+	else if (dwim_ref(start_name, strlen (start_name), sha1, &real_ref))
+		remote = !prefixcmp(real_ref, "refs/remotes/");
+	else
 		die("Not a valid object name: '%s'.", start_name);
 
 	if ((commit = lookup_commit_reference(sha1)) == NULL)
@@ -354,8 +377,16 @@ static void create_branch(const char *name, const char *start_name,
 		snprintf(msg, sizeof msg, "branch: Created from %s",
 			 start_name);
 
+	/* When branching off a remote branch, set up so that git-pull
+	   automatically merges from there.  */
+	if (remote && track)
+		register_pull (name, real_ref + 13);
+
 	if (write_ref_sha1(lock, sha1, msg) < 0)
 		die("Failed to write ref: %s.", strerror(errno));
+
+	if (real_ref)
+		free (real_ref);
 }
 
 static void rename_branch(const char *oldname, const char *newname, int force)
@@ -397,11 +428,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	int delete = 0, force_delete = 0, force_create = 0;
 	int rename = 0, force_rename = 0;
 	int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
-	int reflog = 0;
+	int reflog = 0, track;
 	int kinds = REF_LOCAL_BRANCH;
 	int i;
 
 	git_config(git_branch_config);
+	track = track_remote_branches;
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
@@ -412,6 +444,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 			i++;
 			break;
 		}
+		if (!strcmp(arg, "--track")) {
+			track = 1;
+			continue;
+		}
+		if (!strcmp(arg, "--no-track")) {
+			track = 0;
+			continue;
+		}
 		if (!strcmp(arg, "-d")) {
 			delete = 1;
 			continue;
@@ -490,9 +530,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	else if (rename && (i == argc - 2))
 		rename_branch(argv[i], argv[i + 1], force_rename);
 	else if (i == argc - 1)
-		create_branch(argv[i], head, head_sha1, force_create, reflog);
+		create_branch(argv[i], head, head_sha1, force_create, reflog,
+			      track);
 	else if (i == argc - 2)
-		create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
+		create_branch(argv[i], argv[i+1], NULL, force_create, reflog,
+			      track);
 	else
 		usage(builtin_branch_usage);
 
diff --git a/cache.h b/cache.h
index 8bbc142..585a9b4 100644
--- a/cache.h
+++ b/cache.h
@@ -205,6 +205,7 @@ extern int trust_executable_bit;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
 extern int log_all_ref_updates;
+extern int track_remote_branches;
 extern int warn_ambiguous_refs;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
diff --git a/config.c b/config.c
index 0ff413b..49df7bd 100644
--- a/config.c
+++ b/config.c
@@ -294,6 +294,11 @@ int git_default_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.trackremotebranches")) {
+		track_remote_branches = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "core.legacyheaders")) {
 		use_legacy_headers = git_config_bool(var, value);
 		return 0;
diff --git a/environment.c b/environment.c
index 570e32a..e440d05 100644
--- a/environment.c
+++ b/environment.c
@@ -17,6 +17,7 @@ int assume_unchanged;
 int prefer_symlink_refs;
 int is_bare_repository_cfg = -1; /* unspecified */
 int log_all_ref_updates = -1; /* unspecified */
+int track_remote_branches = 0;
 int warn_ambiguous_refs = 1;
 int repository_format_version;
 char *git_commit_encoding;

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-02  4:49                                     ` Junio C Hamano
@ 2007-03-02  9:05                                       ` Alex Riesen
  2007-03-02  9:57                                         ` Junio C Hamano
  0 siblings, 1 reply; 48+ messages in thread
From: Alex Riesen @ 2007-03-02  9:05 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git

On 3/2/07, Junio C Hamano <junkio@cox.net> wrote:
> "Alex Riesen" <raa.lkml@gmail.com> writes:
>
> > The oldtimers will have no problems changing the default,
> > and the option is properly documented in the patch.
>
> "Old-timers will have no problems" is not a good enough
> justification to change the default.  You need to justify _why_
> it is _they_ who needs to do the extra configuration.
>

I don't know. I wont have any trouble, I think.

I don't even care either way (it is documented, it has
configurable default and it can be switched on or off
in deterministic manner), and will be only slightly
pleased if creation of a tracked branch is more
noticeable (see the mail regarding message on
branch creation).

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02  8:50                                         ` [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch Paolo Bonzini
@ 2007-03-02  9:52                                           ` Junio C Hamano
  2007-03-02  9:55                                             ` Junio C Hamano
                                                               ` (2 more replies)
  0 siblings, 3 replies; 48+ messages in thread
From: Junio C Hamano @ 2007-03-02  9:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Johannes Schindelin, git

Paolo Bonzini <paolo.bonzini@gmail.com> writes:

> A rather standard (in 1.5) procedure for branching off a remote archive
> is:

Much easier to read, thanks.

Although I'll still nitpick a few points...

>
>   git checkout -b branchname remote/upstreambranch
>   git config --add branch.branchname.remote remote
>   git config --add branch.branchname.merge refs/heads/upstreambranch

Probably a rather standard procedure would be to fork from
remote tracking branch of where you cloned from, i.e. under
'remotes/origin'.  I think the above examples are a bit easier
to read if you said:

    In order to track and build on top of a branch 'topic' you
    track from your upstream repository, you often would end up
    doing this sequence:

    $ git checkout -b topic origin/topic
    $ git config --add branch.branchname.remote origin
    $ git config --add branch.branchname.merge refs/heads/topic

    to fork your own 'topic' branch from the corresponding
    branch you track from the 'origin' repository, and set up
    two configuration variables so that 'git pull' without
    parameters does the right thing while you are on your own
    'topic' branch.

    This commit teaches --track option to git-branch, so that
    "git branch --track topic origin/topic" performs the latter
    two actions when creating your 'topic' branch.  By setting
    configuration variable 'branch.trackremotebranches' to true,
    you do not have to pass --track option explicitly (the
    configuration variable is off by default, and there is a
    --no-track option to countermand it even if the variable is
    set).

    Signed-off-by: ...

I do not think a porcelain level command 'branch' should
introduce core.* configuration variables.

I have a feeling that "git checkout -b" and "git checkout -B"
should be taught to explicitly use "git branch --no-track" and
"git branch --track" to create a new branch (currently it does
not even use "git branch" as far as I can tell).  With your
patch, I suspect that you have to say "git branch topic
origin/topic" and then "git checkout topic", which means you
made the three-step process into two steps, but you could have
made it into one step.  I'll send out an untested patch to
git-checkout so that you can try it out in a separate message.

> diff --git a/builtin-branch.c b/builtin-branch.c
> index d0179b0..96658ff 100644
> --- a/builtin-branch.c
> +++ b/builtin-branch.c
> @@ -308,15 +308,34 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
>  	free_ref_list(&ref_list);
>  }
>  
> +static void register_pull (const char *name, const char *remote_branch_name)
> +{
> +	char *slash = strchr(remote_branch_name, '/');
> +	char key[1024], value[1024];
> +
> +	if (strlen(remote_branch_name) >= 1024 - 11
> +	    || strlen(name) >= 1024 - 15)
> +		die ("what a long branch name you have!");
> +
> +	snprintf(key, sizeof(key), "branch.%s.remote", name);
> +	snprintf(value, sizeof(value), "%.*s", slash - remote_branch_name,
> +		 remote_branch_name);
> +	git_config_set(key, value);
> +
> +	snprintf(key, sizeof(key), "branch.%s.merge", name);
> +	snprintf(value, sizeof(value), "refs/heads/%s", slash + 1);
> +	git_config_set(key, value);
> +}
> +

 - (minor style) No SP between "register_pull" and "(".  Found
   elsewhere as well.

 - (minor style) I tend to prefer pure declarations before decls
   with initializer.  I.e. "char key[], value[]" first then
   "char *slash".

 - (discipline) Not 1024 in the comparison.  sizeof(key) or
   sizeof(value).

 - (micronit) Is it true that both strlen() tests are about long
   *branch* names?

 - (style and discipline) If you use snprintf(), it is usually
   easier to check its return value to see if you would have
   overflowed, without having the if() statement to check the
   length upfront.  As the code gets updated, you may need to
   change the snprintf() format strings later, and you can
   forget making a matching change to the condition in if()
   statement with the patch above.

 - (moderately serious) The code blindly trusts that
   "refs/remotes/foo/bar" tracks "refs/heads/bar" from remote
   named "foo", which is a bit disturbing.  With the default
   configuration git-clone and git-remote creates, it always is
   the case, but I suspect you might want to at least verify
   that assumption (the user can have different settings in the
   config), if not figuring them out by reading the existing
   configuration yourself.

> @@ -333,7 +354,9 @@ static void create_branch(const char *name, const char *start_name,
>  	if (start_sha1)
>  		/* detached HEAD */
>  		hashcpy(sha1, start_sha1);
> -	else if (get_sha1(start_name, sha1))
> +	else if (dwim_ref(start_name, strlen(start_name), sha1, &real_ref))
> +		remote = !prefixcmp(real_ref, "refs/remotes/");
> +	else
>  		die("Not a valid object name: '%s'.", start_name);
>  
>  	if ((commit = lookup_commit_reference(sha1)) == NULL)

 - (pure question) What happens if dwim_ref() returns more than one?

> diff --git a/config.c b/config.c
> index 0ff413b..49df7bd 100644
> --- a/config.c
> +++ b/config.c
> @@ -294,6 +294,11 @@ int git_default_config(const char *var, const char *value)
>  		return 0;
>  	}
>  
> +	if (!strcmp(var, "core.trackremotebranches")) {
> +		track_remote_branches = git_config_bool(var, value);
> +		return 0;
> +	}
> +
>  	if (!strcmp(var, "core.legacyheaders")) {
>  		use_legacy_headers = git_config_bool(var, value);
>  		return 0;

 - (mild objection) Does this belong to git_default_config()?  I
   would have expected this to appear in git_branch_config().

> diff --git a/environment.c b/environment.c
> index 570e32a..e440d05 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -17,6 +17,7 @@ int assume_unchanged;
>  int prefer_symlink_refs;
>  int is_bare_repository_cfg = -1; /* unspecified */
>  int log_all_ref_updates = -1; /* unspecified */
> +int track_remote_branches = 0;
>  int warn_ambiguous_refs = 1;
>  int repository_format_version;
>  char *git_commit_encoding;

 - (style and discipline) No need to initialize global int to
   0.  BSS would take care of it.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02  9:52                                           ` Junio C Hamano
@ 2007-03-02  9:55                                             ` Junio C Hamano
  2007-03-02 10:32                                             ` Jeff King
  2007-03-02 11:14                                             ` Paolo Bonzini
  2 siblings, 0 replies; 48+ messages in thread
From: Junio C Hamano @ 2007-03-02  9:55 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Johannes Schindelin, git

Junio C Hamano <junkio@cox.net> writes:

> I have a feeling that "git checkout -b" and "git checkout -B"
> should be taught to explicitly use "git branch --no-track" and
> "git branch --track" to create a new branch (currently it does
> not even use "git branch" as far as I can tell).  With your
> patch, I suspect that you have to say "git branch topic
> origin/topic" and then "git checkout topic", which means you
> made the three-step process into two steps, but you could have
> made it into one step.  I'll send out an untested patch to
> git-checkout so that you can try it out in a separate message.

This does not add -B because I haven't applied your patch to my
tree yet, but it should be obvious where to add --track/--no-track.

Oh, as usual, I only have tested it once, so it may or may not
work.


diff --git a/git-checkout.sh b/git-checkout.sh
index 14835a4..bdf5cdf 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -33,7 +33,7 @@ while [ "$#" != "0" ]; do
 			die "git checkout: we do not like '$newbranch' as a branch name."
 		;;
 	"-l")
-		newbranch_log=1
+		newbranch_log=-l
 		;;
 	"-f")
 		force=1
@@ -235,11 +235,7 @@ fi
 #
 if [ "$?" -eq 0 ]; then
 	if [ "$newbranch" ]; then
-		if [ "$newbranch_log" ]; then
-			mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$newbranch")
-			touch "$GIT_DIR/logs/refs/heads/$newbranch"
-		fi
-		git-update-ref -m "checkout: Created from $new_name" "refs/heads/$newbranch" $new || exit
+		git branch $newbranch_log "$newbranch" "$new_name" || exit
 		branch="$newbranch"
 	fi
 	if test -n "$branch"

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3)
  2007-03-02  9:05                                       ` Alex Riesen
@ 2007-03-02  9:57                                         ` Junio C Hamano
  0 siblings, 0 replies; 48+ messages in thread
From: Junio C Hamano @ 2007-03-02  9:57 UTC (permalink / raw)
  To: Alex Riesen
  Cc: bonzini, Johannes Schindelin, Julian Phillips, Andy Parkins, git

"Alex Riesen" <raa.lkml@gmail.com> writes:

> ..., and will be only slightly
> pleased if creation of a tracked branch is more
> noticeable (see the mail regarding message on
> branch creation).

I would very much agree on this part, regardless of what the
default would end up to be.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02  9:52                                           ` Junio C Hamano
  2007-03-02  9:55                                             ` Junio C Hamano
@ 2007-03-02 10:32                                             ` Jeff King
  2007-03-02 11:15                                               ` Paolo Bonzini
  2007-03-02 11:14                                             ` Paolo Bonzini
  2 siblings, 1 reply; 48+ messages in thread
From: Jeff King @ 2007-03-02 10:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Paolo Bonzini, Johannes Schindelin, git

On Fri, Mar 02, 2007 at 01:52:29AM -0800, Junio C Hamano wrote:

>  - (moderately serious) The code blindly trusts that
>    "refs/remotes/foo/bar" tracks "refs/heads/bar" from remote
>    named "foo", which is a bit disturbing.  With the default
>    configuration git-clone and git-remote creates, it always is
>    the case, but I suspect you might want to at least verify
>    that assumption (the user can have different settings in the
>    config), if not figuring them out by reading the existing
>    configuration yourself.

Sorry to come into this conversation a bit late, but I am catching up on
git reading. I agree that this assumption seems a bit suspect; this is
the exact sort of thing I was envisioning a 'mergeLocal' or similar
config option for; it avoids the need to make the reverse mapping.

In fact, the way I thought about it was that branching might set the
branch.*.branched_from variable. Then any porcelain which wanted
to have a sane default for various operations (merge, rebase, etc) could
use their regular, user-specified config (e.g., merge checks
branch.*.merge; if not set, it defaults to branch.*.branched_from; if
not set, barf).

Thus you are compatible with the config features we have now, but in the
case where we would currently die, this gives another option. It is
safer to remove this variable on branch deletion (I know some people
raised concerns about automatically removing parts of the config file)
because the user would never set 'branched_from'; they would set
'merge'.

IOW, my point is that branching should write the information it _knows_
into the config: branch X was branched from branch Y. It should be up to
the programs to _use_ that information in a reasonable way. As it is
now, this patch makes the decision about how to use the information at
the time of branching, which seems to be the source of a lot of objects.

My 2 cents,
-Peff

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02  9:52                                           ` Junio C Hamano
  2007-03-02  9:55                                             ` Junio C Hamano
  2007-03-02 10:32                                             ` Jeff King
@ 2007-03-02 11:14                                             ` Paolo Bonzini
  2007-03-02 15:54                                               ` Johannes Schindelin
  2 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-02 11:14 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Paolo Bonzini, Johannes Schindelin, git

> I have a feeling that "git checkout -b" and "git checkout -B"
> should be taught to explicitly use "git branch --no-track" and
> "git branch --track" to create a new branch (currently it does
> not even use "git branch" as far as I can tell).  With your
> patch, I suspect that you have to say "git branch topic
> origin/topic" and then "git checkout topic", which means you
> made the three-step process into two steps, but you could have
> made it into one step.

Well, yes, the next part would have been to patch git-checkout.  But this one is already proving to be complicated enough.  :-)

> I'll send out an untested patch to
> git-checkout so that you can try it out in a separate message.

I saw it.  I tested your patch and it seems to work.
 
>  - (micronit) Is it true that both strlen() tests are about long
>    *branch* names?

If you consider something like "origin/next" to be a branch name, yes.

>  - (moderately serious) The code blindly trusts that
>    "refs/remotes/foo/bar" tracks "refs/heads/bar" from remote
>    named "foo", which is a bit disturbing.  With the default
>    configuration git-clone and git-remote creates, it always is
>    the case, but I suspect you might want to at least verify
>    that assumption (the user can have different settings in the
>    config), if not figuring them out by reading the existing
>    configuration yourself.

Ouch.  Absolutely right, but this means I will prepare the patch later then.

>> +	else if (dwim_ref(start_name, strlen(start_name), sha1, &real_ref))
>> +		remote = !prefixcmp(real_ref, "refs/remotes/");
> 
>  - (pure question) What happens if dwim_ref() returns more than one?

Then, real_ref is the one matching sha1.

Considering your other objection about the naming of the variable, what about enabling/disabling the tracking using remote.REMOTENAME.tracklocalsubbranches?

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02 10:32                                             ` Jeff King
@ 2007-03-02 11:15                                               ` Paolo Bonzini
  2007-03-02 11:21                                                 ` Jeff King
  0 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-02 11:15 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, Paolo Bonzini, Johannes Schindelin, git


> IOW, my point is that branching should write the information it _knows_
> into the config: branch X was branched from branch Y. It should be up to
> the programs to _use_ that information in a reasonable way. As it is
> now, this patch makes the decision about how to use the information at
> the time of branching, which seems to be the source of a lot of objects.

The problem is that this will pollute the configuration file a lot.  I'm starting to wonder if all this branch information really belongs in .git/config at all.

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3, inline)
  2007-03-02  8:10                                       ` Paolo Bonzini
  2007-03-02  8:50                                         ` [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch Paolo Bonzini
@ 2007-03-02 11:19                                         ` Johannes Schindelin
  1 sibling, 0 replies; 48+ messages in thread
From: Johannes Schindelin @ 2007-03-02 11:19 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Junio C Hamano, git

Hi,

On Fri, 2 Mar 2007, Paolo Bonzini wrote:

> >> +	remote_value[slash - remote_name] = 0;
> > 
> > You should check if slash == NULL and error out before using it.
> 
> remote_name is of the form "REMOTE/BRANCH", because it comes from 
> dwim_ref's output after stripping "refs/remotes/" from the beginning.

You can create a new "remote" branch anytime by

	$ git update-ref refs/remotes/lirumlarum HEAD

Your code would realize that it is a remote ref, strip "refs/remotes/", 
and then call strchr("lirumlarum", '/'), which returns NULL.

On a related note, it _might_ make sense to check that the remote 
information is set as expected:

	static const char *remote_name;
	static int found_remote, remote_name_len;

	static int find_remote(const char *key, const char *value) {
		/*
		 * This checks if
		 * remote.<bla>.fetch == refs/heads/*:refs/heads/<bla>/*
		 * where <bla> is the remote_name.
		 */
		if (!prefixcmp(key, "remote.") &&
				!prefixcmp(key + 7, remote_name) && 
				!strcmp(key + 7 + remote_name_len,
					 ".fetch") &&
				value &&
				!prefixcmp(value, 
					"refs/heads/*:refs/remotes/") &&
				!prefixcmp(value + 26, remote_name) &&
				!strcmp(value + 26 + remote_name, "/*")) {
			found_remote = 1;
			return -1; /* stop parsing config */
		}
		return 0;
	}

and then in remote_pull():

	found_remote = 0;
	remote_name = branch_name;
	remote_name_len = slash - branch_name;
	git_config(find_remote);
	if (!found_remote) {
		warn("Remote %s was not created with git-remote; "
			"will not add it as default merge source to %s",
			branch_name, name);
		return;
	}

We could rely on new git users not to fiddle with the remote information 
in the config, and old-timers still using .git/remotes/ or .git/branches 
would be told why the default merge information was not set up.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02 11:15                                               ` Paolo Bonzini
@ 2007-03-02 11:21                                                 ` Jeff King
  0 siblings, 0 replies; 48+ messages in thread
From: Jeff King @ 2007-03-02 11:21 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Junio C Hamano, Johannes Schindelin, git

On Fri, Mar 02, 2007 at 12:15:59PM +0100, Paolo Bonzini wrote:

> > the time of branching, which seems to be the source of a lot of objects.

Err, this should be "the source of a lot of objections" of course.

> The problem is that this will pollute the configuration file a lot.
> I'm starting to wonder if all this branch information really belongs
> in .git/config at all.

I'm not sure how this pollutes any more than the existing proposal. But
I have always been a bit uncomfortable with automatic editing of the
user config (having used such programs in the past, it always seems to
cause subtle annoyances -- however, I find I don't even use the per-repo
config in most cases, but just the ~/.gitconfig).

Perhaps if we had an inclusion mechanism, all automatically written
configuration could go into $GIT_DIR/auto_config with a big warning at
the top, and the .git/config could include it.

Or are you concerned with just polluting the config namespace? Obviously
we could store per-branch metadata somewhere else, but I think there has
been a push to put it _into_ the config over the past several months,
instead of in a separate file.

-Peff

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH] defaults for where to merge from (take 3, inline)
  2007-03-01 22:01                                     ` Johannes Schindelin
  2007-03-02  8:10                                       ` Paolo Bonzini
@ 2007-03-02 14:10                                       ` Jakub Narebski
  1 sibling, 0 replies; 48+ messages in thread
From: Jakub Narebski @ 2007-03-02 14:10 UTC (permalink / raw)
  To: git

Johannes Schindelin wrote:
>On Thu, 1 Mar 2007, Paolo Bonzini wrote:

>>  
>> +static void register_branch_pull (const char *name, const char
*remote_name)
> 
> It is not yet remote_name, right? it is branch_name. You extract the 
> remote_name by finding the first slash.

I'm bit reluctant about this, as it is not required that remote
names cannot contain slashes. But remotes with slashes would make
separation into remote and tracking branch part more difficult.

>> +{
>> +     char *slash = strchr(remote_name, '/');
>> +
>> +     char *config_key = xmalloc(strlen(name) + 15);
>> +     char *merge_value = xmalloc(strlen(remote_name) + 10);
>> +
>> +     char *remote_value = xstrdup(remote_name);
> 
> I'd use "char key[1024], value[1024]" instead, erroring out if one of the 
> buffers are too small. It's not like you have to be memory efficient, and 
> it is easier to read.

The config parser has lengths limits on fully qualified key name (with
section name and subsection name) _and_ on value name. Use them, please,
instead of dynamic allocation and troubles with those.

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: defaults for where to merge from
  2007-03-01  8:18                     ` Junio C Hamano
@ 2007-03-02 15:53                       ` J. Bruce Fields
  0 siblings, 0 replies; 48+ messages in thread
From: J. Bruce Fields @ 2007-03-02 15:53 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Alex Riesen, bonzini, Johannes Schindelin, Julian Phillips,
	Andy Parkins, git

On Thu, Mar 01, 2007 at 12:18:58AM -0800, Junio C Hamano wrote:
> "Alex Riesen" <raa.lkml@gmail.com> writes:
> 
> >> If everyone hated the old behavior, old users should already be careful
> >> about not git-pull'ing (without options) from any branch but master.  So
> >> they won't see any difference.
> >
> > except for .git/config growing uncontrollably
> 
> I think this should be a new option, not the _modified default_.
> Otherwise it would be harder to sell to olde timers.
> 
> 	$ git checkout -B <newbranch> remotes/<blah>
>         $ git branch --track <newbranch> remotes/<blah>
> 
> might be a good compromise.

Personally I usually use <blah> as <newbranch>.  I might have gone for
something like

	git remote checkout [remote] blah [-b newbranch]

with defaulted to newbranch = blah.

--b.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02 11:14                                             ` Paolo Bonzini
@ 2007-03-02 15:54                                               ` Johannes Schindelin
  2007-03-02 16:33                                                 ` Paolo Bonzini
  0 siblings, 1 reply; 48+ messages in thread
From: Johannes Schindelin @ 2007-03-02 15:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Junio C Hamano, git

Hi,

On Fri, 2 Mar 2007, Paolo Bonzini wrote:

> >  - (micronit) Is it true that both strlen() tests are about long
> >    *branch* names?

Yes. "name" refers to the _new_ branch, and "remote_branch_name" refers to 
the remote branch.

> >  - (moderately serious) The code blindly trusts that
> >    "refs/remotes/foo/bar" tracks "refs/heads/bar" from remote
> >    named "foo", which is a bit disturbing.  With the default
> >    configuration git-clone and git-remote creates, it always is
> >    the case, but I suspect you might want to at least verify
> >    that assumption (the user can have different settings in the
> >    config), if not figuring them out by reading the existing
> >    configuration yourself.
> 
> Ouch.  Absolutely right, but this means I will prepare the patch later 
> then.

I really recommend doing what I said in another reply: check that 
the remote information in the config for that remote meets our 
expectations. And do nothing at all if it does not (maybe warn that no 
branch.<foo> voodoo was done).

> >> +	else if (dwim_ref(start_name, strlen(start_name), sha1, &real_ref))
> >> +		remote = !prefixcmp(real_ref, "refs/remotes/");
> > 
> >  - (pure question) What happens if dwim_ref() returns more than one?
> 
> Then, real_ref is the one matching sha1.

Which one ;-)

What Junio tried to get at: if you have "refs/heads/my" and 
"refs/remotes/origin/my", dwim_ref("my", ...) returns 2 (or even more, if 
you have other refs ending in "/my").

Please test if the return value is exactly 1, and if it is not, do 
nothing.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02 15:54                                               ` Johannes Schindelin
@ 2007-03-02 16:33                                                 ` Paolo Bonzini
  2007-03-02 19:06                                                   ` Johannes Schindelin
  0 siblings, 1 reply; 48+ messages in thread
From: Paolo Bonzini @ 2007-03-02 16:33 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Paolo Bonzini, Junio C Hamano, git


>>>> +	else if (dwim_ref(start_name, strlen(start_name), sha1, &real_ref))
>>>> +		remote = !prefixcmp(real_ref, "refs/remotes/");
>>>  - (pure question) What happens if dwim_ref() returns more than one?
>> Then, real_ref is the one matching sha1.
> 
> Which one ;-)

Matching "the variable named" sha1. :-)

> What Junio tried to get at: if you have "refs/heads/my" and 
> "refs/remotes/origin/my", dwim_ref("my", ...) returns 2 (or even more, if 
> you have other refs ending in "/my").

But the sha1 and the real_ref are always consistent.  If I get refs/heads/my (and a non-remote will always override the remote), the sha1 is non remote.  If I get refs/remotes/origin/my (which triggers the magic), the sha1 is remote.

Still, let's put this patch on hold, I have to understand more about git before proposing something that is clearly beyond my knowledge (as the criticism shows).

Paolo

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch
  2007-03-02 16:33                                                 ` Paolo Bonzini
@ 2007-03-02 19:06                                                   ` Johannes Schindelin
  0 siblings, 0 replies; 48+ messages in thread
From: Johannes Schindelin @ 2007-03-02 19:06 UTC (permalink / raw)
  To: bonzini; +Cc: Paolo Bonzini, Junio C Hamano, git

Hi,

On Fri, 2 Mar 2007, Paolo Bonzini wrote:

> >>>> +	else if (dwim_ref(start_name, strlen(start_name), sha1, &real_ref))
> >>>> +		remote = !prefixcmp(real_ref, "refs/remotes/");
> >>>  - (pure question) What happens if dwim_ref() returns more than one?
> >> Then, real_ref is the one matching sha1.
> > 
> > Which one ;-)
> 
> Matching "the variable named" sha1. :-)
> 
> > What Junio tried to get at: if you have "refs/heads/my" and 
> > "refs/remotes/origin/my", dwim_ref("my", ...) returns 2 (or even more, 
> > if you have other refs ending in "/my").
> 
> But the sha1 and the real_ref are always consistent.  If I get 
> refs/heads/my (and a non-remote will always override the remote), the 
> sha1 is non remote.  If I get refs/remotes/origin/my (which triggers the 
> magic), the sha1 is remote.

Okay, but you can have "refs/remotes/origin/my" and 
"refs/remotes/paolo/my".

> Still, let's put this patch on hold, I have to understand more about git 
> before proposing something that is clearly beyond my knowledge (as the 
> criticism shows).

I think you are doing fine. Since there is a lot of discussion about this 
feature, it does clearly not fail the mark. A little bit more work, and it 
is ready for inclusion IMHO.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2007-03-02 19:07 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-28 14:53 defaults for where to merge from Paolo Bonzini
2007-02-28 15:13 ` Johannes Schindelin
2007-02-28 15:22 ` Andy Parkins
2007-02-28 15:30   ` Paolo Bonzini
2007-02-28 15:43     ` Andy Parkins
2007-02-28 15:30   ` Julian Phillips
2007-02-28 15:46     ` Johannes Schindelin
2007-02-28 17:11       ` Paolo Bonzini
2007-02-28 18:06         ` Johannes Schindelin
2007-03-01  7:52           ` [PATCH] defaults for where to merge from (take 2) Paolo Bonzini
2007-02-28 18:45       ` defaults for where to merge from Alex Riesen
2007-02-28 19:56         ` Paolo Bonzini
2007-03-01  0:07           ` Alex Riesen
2007-03-01  1:25             ` Johannes Schindelin
2007-03-01  7:55               ` Alex Riesen
2007-03-01  8:02                 ` Paolo Bonzini
2007-03-01  8:10                   ` Alex Riesen
2007-03-01  8:18                     ` Junio C Hamano
2007-03-02 15:53                       ` J. Bruce Fields
2007-03-01  8:29                     ` Paolo Bonzini
2007-03-01  8:33                       ` Alex Riesen
2007-03-01  8:45                         ` Paolo Bonzini
2007-03-01  8:59                           ` Alex Riesen
2007-03-01  9:37                             ` [PATCH] defaults for where to merge from (take 3) Paolo Bonzini
2007-03-01 10:12                               ` Alex Riesen
2007-03-01 10:17                                 ` Paolo Bonzini
2007-03-01 10:27                                 ` Junio C Hamano
2007-03-01 10:42                                   ` Alex Riesen
2007-03-02  4:49                                     ` Junio C Hamano
2007-03-02  9:05                                       ` Alex Riesen
2007-03-02  9:57                                         ` Junio C Hamano
2007-03-01 10:47                                   ` Alex Riesen
2007-03-01 16:33                                   ` [PATCH] defaults for where to merge from (take 3, inline) Paolo Bonzini
2007-03-01 22:01                                     ` Johannes Schindelin
2007-03-02  8:10                                       ` Paolo Bonzini
2007-03-02  8:50                                         ` [PATCH, 4th version] git-branch: register where to merge from, when branching off a remote branch Paolo Bonzini
2007-03-02  9:52                                           ` Junio C Hamano
2007-03-02  9:55                                             ` Junio C Hamano
2007-03-02 10:32                                             ` Jeff King
2007-03-02 11:15                                               ` Paolo Bonzini
2007-03-02 11:21                                                 ` Jeff King
2007-03-02 11:14                                             ` Paolo Bonzini
2007-03-02 15:54                                               ` Johannes Schindelin
2007-03-02 16:33                                                 ` Paolo Bonzini
2007-03-02 19:06                                                   ` Johannes Schindelin
2007-03-02 11:19                                         ` [PATCH] defaults for where to merge from (take 3, inline) Johannes Schindelin
2007-03-02 14:10                                       ` Jakub Narebski
2007-02-28 17:31   ` defaults for where to merge from Peter Baumann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.