threads / patch / 13322

patchAllow local branching to set up rebase by default.

Subject: [PATCH] Allow local branching to set up rebase by default.

## tl;dr

12 messages between Apr 29, 2008 and May 10, 2008. Diffs are folded; open one to read it.

replies: 11people: 3as markdown or json

Dustin Sallings· Apr 29, 2008, 20:49 UTC · lore

Change cd67e4d4 introduced a new configuration parameter that told pull to automatically perform a rebase instead of a merge. I use this feature quite a bit in topic branches and would like it to be the default behavior for a topic branch.

If the parameter branch.autosetuprebase applies for a branch that's being created, that branch will have branch.<name>.rebase set to true.

See the documentation for how this may be applied.
New model.
---
 Documentation/config.txt |   14 +++++++
 branch.c                 |   26 ++++++++++++-
 cache.h                  |    8 ++++
 config.c                 |   14 +++++++
 environment.c            |    1 +
 t/t3200-branch.sh        |   92 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 154 insertions(+), 1 deletions(-)
Show changes to 6 files +154 −1

Documentation/config.txt, branch.c, cache.h, config.c, environment.c, t/t3200-branch.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 7a24f6e..1994895 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -393,6 +393,20 @@ branch.autosetupmerge::
 	done when the starting point is either a local branch or remote
 	branch. This option defaults to true.
 
+branch.autosetuprebase::
+	When a new branch is created with `git-branch` or `git-checkout`
+	that tracks another branch, this parameter tells git to set
+	up pull to rebase instead of merge (see "branch.<name>.rebase")
+	below.
+	When `never`, rebase is never automatically set to true.
+	When `local`, rebase is set to true for tracked branches of
+	other local branches.
+	When `remote`, rebase is set to true for tracked branches of
+	remote branches.
+	When `always`, rebase will be set to true for all tracking
+	branches.
+	This option defaults to never.
+
 branch.<name>.remote::
 	When in branch <name>, it tells `git fetch` which remote to fetch.
 	If this option is not given, `git fetch` defaults to remote "origin".
diff --git a/branch.c b/branch.c
index daf862e..2a731e4 100644
--- a/branch.c
+++ b/branch.c
@@ -32,6 +32,25 @@ static int find_tracked_branch(struct remote *remote, void *priv)
 	return 0;
 }
 
+static int should_setup_rebase(struct tracking tracking) {
+	int rv=0;
+	switch(autorebase) {
+	case AUTOREBASE_NEVER:
+		rv = 0;
+		break;
+	case AUTOREBASE_LOCAL:
+		rv = tracking.matches == 0;
+		break;
+	case AUTOREBASE_REMOTE:
+		rv = tracking.matches > 0;
+		break;
+	case AUTOREBASE_ALWAYS:
+		rv = 1;
+		break;
+	}
+	return rv;
+}
+
 /*
  * This is called when new_ref is branched off of orig_ref, and tries
  * to infer the settings for branch.<new_ref>.{remote,merge} from the
@@ -69,9 +88,14 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
 	git_config_set(key, tracking.remote ?  tracking.remote : ".");
 	sprintf(key, "branch.%s.merge", new_ref);
 	git_config_set(key, tracking.src ? tracking.src : orig_ref);
-	free(tracking.src);
 	printf("Branch %s set up to track %s branch %s.\n", new_ref,
 		tracking.remote ? "remote" : "local", orig_ref);
+	if (should_setup_rebase(tracking)) {
+		sprintf(key, "branch.%s.rebase", new_ref);
+		git_config_set(key, "true");
+		printf("This branch will rebase on pull.\n");
+	}
+	free(tracking.src);
 
 	return 0;
 }
diff --git a/cache.h b/cache.h
index 3fcc283..5c9aff8 100644
--- a/cache.h
+++ b/cache.h
@@ -433,7 +433,15 @@ enum branch_track {
 	BRANCH_TRACK_EXPLICIT,
 };
 
+enum rebase_setup_type {
+	AUTOREBASE_NEVER = 0,
+	AUTOREBASE_LOCAL,
+	AUTOREBASE_REMOTE,
+	AUTOREBASE_ALWAYS,
+};
+
 extern enum branch_track git_branch_track;
+extern enum rebase_setup_type autorebase;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
diff --git a/config.c b/config.c
index b0ada51..2959087 100644
--- a/config.c
+++ b/config.c
@@ -487,6 +487,20 @@ int git_default_config(const char *var, const char *value)
 		git_branch_track = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "branch.autosetuprebase")) {
+		if (!strcmp(value, "never"))
+			autorebase = AUTOREBASE_NEVER;
+		else if (!strcmp(value, "local"))
+			autorebase = AUTOREBASE_LOCAL;
+		else if (!strcmp(value, "remote"))
+			autorebase = AUTOREBASE_REMOTE;
+		else if (!strcmp(value, "always"))
+			autorebase = AUTOREBASE_ALWAYS;
+		else
+			die_bad_config(
+				"Invalid value for branch.autosetupmerge");
+		return 0;
+	}
 
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
diff --git a/environment.c b/environment.c
index 6739a3f..6fb3b97 100644
--- a/environment.c
+++ b/environment.c
@@ -38,6 +38,7 @@ int auto_crlf = 0;	/* 1: both ways, -1: only when adding git objects */
 enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
+enum rebase_setup_type autorebase = 0;
 
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index cb5f7a4..10bb429 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -224,4 +224,96 @@ test_expect_success 'avoid ambiguous track' '
 	test -z "$(git config branch.all1.merge)"
 '
 
+test_expect_success 'autosetuprebase local on a tracked local branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase local &&
+	 (git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	 git branch mybase &&
+	 git branch --track myr1 mybase &&
+	 test "$(git config branch.myr1.remote)" = . &&
+	 test "$(git config branch.myr1.merge)" = refs/heads/mybase &&
+	 test "$(git config branch.myr1.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked local branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase always &&
+	 (git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	 git branch mybase2 &&
+	 git branch --track myr2 mybase &&
+	 test "$(git config branch.myr2.remote)" = . &&
+	 test "$(git config branch.myr2.merge)" = refs/heads/mybase &&
+	 test "$(git config branch.myr2.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked local branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase remote &&
+	 (git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	 git branch mybase3 &&
+	 git branch --track myr3 mybase2 &&
+	 test "$(git config branch.myr3.remote)" = . &&
+	 test "$(git config branch.myr3.merge)" = refs/heads/mybase2 &&
+	 ! test "$(git config branch.myr3.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked local branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase never &&
+	 (git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	 git branch mybase4 &&
+	 git branch --track myr4 mybase2 &&
+	 test "$(git config branch.myr4.remote)" = . &&
+	 test "$(git config branch.myr4.merge)" = refs/heads/mybase2 &&
+	 ! test "$(git config branch.myr4.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase local on a tracked remote branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase local &&
+	 (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	 git branch --track myr5 local/master &&
+	 test "$(git config branch.myr5.remote)" = local &&
+	 test "$(git config branch.myr5.merge)" = refs/heads/master &&
+	 ! test "$(git config branch.myr5.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked remote branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase never &&
+	 (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	 git branch --track myr6 local/master &&
+	 test "$(git config branch.myr6.remote)" = local &&
+	 test "$(git config branch.myr6.merge)" = refs/heads/master &&
+	 ! test "$(git config branch.myr6.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked remote branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase remote &&
+	 (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	 git branch --track myr7 local/master &&
+	 test "$(git config branch.myr7.remote)" = local &&
+	 test "$(git config branch.myr7.merge)" = refs/heads/master &&
+	 test "$(git config branch.myr7.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked remote branch' \
+	'git config remote.local.url . &&
+	 git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	 git config branch.autosetuprebase remote &&
+	 (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	 git branch --track myr8 local/master &&
+	 test "$(git config branch.myr8.remote)" = local &&
+	 test "$(git config branch.myr8.merge)" = refs/heads/master &&
+	 test "$(git config branch.myr8.rebase)" = true
+'
+
 test_done
-- 
1.5.5.1.100.g65b98
Jay Soffian· Apr 29, 2008, 21:56 UTC · re: Dustin Sallings · lore

Re: [PATCH] Allow local branching to set up rebase by default.

On Tue, Apr 29, 2008 at 4:49 PM, Dustin Sallings <dustin@spy.net> wrote:
Show 10 quoted lines
> Change cd67e4d4 introduced a new configuration parameter that told
>  pull to automatically perform a rebase instead of a merge.  I use this
>  feature quite a bit in topic branches and would like it to be the
>  default behavior for a topic branch.
>
>  If the parameter branch.autosetuprebase applies for a branch that's
>  being created, that branch will have branch.<name>.rebase set to true.
>
>  See the documentation for how this may be applied.
>

I've had this change parked in one of my branches forever. Consider this a UI suggestion to go with the new config option?

    [WIP] new --rebase option to set branch.*.rebase for new branches
    Add a --rebase option to git-branch and git-checkout. If given, it
    implies --track but additionally sets branch.<newbranch>.rebase to true.
    [NOTE TO SELF: this is based off the old next branch, and also it sitting on
    top of my old --track changes, so it will need to be reworked.]
Junio C Hamano· May 7, 2008, 16:22 UTC · re: Dustin Sallings · lore

Re: [PATCH] Allow local branching to set up rebase by default.

Dustin Sallings <dustin@spy.net> writes:
Show 12 quoted lines
> Change cd67e4d4 introduced a new configuration parameter that told
> pull to automatically perform a rebase instead of a merge.  I use this
> feature quite a bit in topic branches and would like it to be the
> default behavior for a topic branch.
>
> If the parameter branch.autosetuprebase applies for a branch that's
> being created, that branch will have branch.<name>.rebase set to true.
>
> See the documentation for how this may be applied.
>
> New model.
> ---

The commit log message is both a sales pitch to get people interested in your change and an explanation of why the change was needed once it gets etched into the history.

The above starts out very nicely by stating the background of the change in the first sentence. However, "I use this ..." is too subjective and makes others on the list who would comment on it go "Huh, you do? So what?" and lose interest in the patch. You got no reactions, neither positive nor negative, partly due to this sentence, I suspect. It would be better received if you make it less subjective (e.g. 'This can be used to maintain tidy history of topic branches until they get merged, but having to say "git pull --rebase" every time is a nuisance.").

With the background and motivation clearly explained, then you would describe what the change solves and how. The second paragraph is fine.

"See the documentation" is a key phrase to turn off people's interest; you would never want to say it, for two reasons:

 (1) people are busy and first scan only the commit log message without
     reading diffs, so that they do not have to waste time on patches that
     are ill conceived.
 (2) once the change is committed, people read "git log" output to get
     overview of the history, and expect the commit log messages to be
     sufficient for that purpose.

"See the doc" tells the reader that "What I have here in the commit log is insufficient and useless; you need to go to the documentation". But that is not the case for your commit log message --- you gave a very good overview and ruined it by having this needless sentence. Drop it.

"New model."???
I certainly went "Huh?" and stopped reading when I hit that line.
Please sign-off your patches (see Documentation/SubmittingPatches).
Show 11 quoted lines
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 7a24f6e..1994895 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -393,6 +393,20 @@ branch.autosetupmerge::
>  	done when the starting point is either a local branch or remote
>  	branch. This option defaults to true.
>  
> +branch.autosetuprebase::
> +	When a new branch is created with `git-branch` or `git-checkout`
> +	that tracks another branch, this parameter tells git to set
This is probably not a "parameter" but a "variable".
> +	up pull to rebase instead of merge (see "branch.<name>.rebase")
> +	below.
"below"?
Show 8 quoted lines
> +	When `never`, rebase is never automatically set to true.
> +	When `local`, rebase is set to true for tracked branches of
> +	other local branches.
> +	When `remote`, rebase is set to true for tracked branches of
> +	remote branches.
> +	When `always`, rebase will be set to true for all tracking
> +	branches.
> +	This option defaults to never.

How does this interact with a similarly named configuration option, autosetupmerge, whose settings can be false, true, and always?

>  branch.<name>.remote::
>  	When in branch <name>, it tells `git fetch` which remote to fetch.
>  	If this option is not given, `git fetch` defaults to remote "origin".

This is not your fault, but can anybody guess what the exact command sequence to cause the named branch to be advanced by rebasing, only by reading this entry?

    branch.<name>.rebase::
            When true, rebase the branch <name> on top of the fetched branch,
            instead of merging the default branch from the default remote.

I can't. Perhaps we would need "when "git pull" is run" or something at the end.

Show 9 quoted lines
> diff --git a/branch.c b/branch.c
> index daf862e..2a731e4 100644
> --- a/branch.c
> +++ b/branch.c
> @@ -32,6 +32,25 @@ static int find_tracked_branch(struct remote *remote, void *priv)
>  	return 0;
>  }
>  
> +static int should_setup_rebase(struct tracking tracking) {
Style.
 - The "{" to start a function body comes at the beginning on its own
   line.
 - Pass struct (especially a read-only one) by a (const) pointer, not by
   value:
	static int foo(const struct tracking *tracking)
        {
        	...
> +	int rv=0;
Style.  s/=/ = /;
> +	switch(autorebase) {
Style. s/(/ (/;
Show 6 quoted lines
> +	case AUTOREBASE_NEVER:
> +		rv = 0;
> +		break;
> +	case AUTOREBASE_LOCAL:
> +		rv = tracking.matches == 0;
> +		break;

Is this correct? Earlier you said "local" is about a branch that trails other local branches, but this seems to be checking only if the branch is not tracking anything remote. Would it be possible for this branch to be not trailing anything, not even local?

	The answer turns out to be "no", only because this function
	implicitly relies on the fact that setup_tracking() never calls it
	if the branch does not track anything, but it was hard to guess
	during the first pass.

You might want to check how the setup_tracking() decides when to say remote/local in its printf().

> +	case AUTOREBASE_REMOTE:
> +		rv = tracking.matches > 0;
> +		break;

This somehow feels awkward because (tracking->matches > 1) is an ambiguous situation (perhaps a misconfiguration) that setup_tracking() rejects but you are allowing it here. Admittedly, the former would never call you when it detects the case, but it still feels awkward...

Show 6 quoted lines
> +	case AUTOREBASE_ALWAYS:
> +		rv = 1;
> +		break;
> +	}
> +	return rv;
> +}

After all you might be better off without a temporary variable rv and return from within the switch().

Show 31 quoted lines
> diff --git a/cache.h b/cache.h
> index 3fcc283..5c9aff8 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -433,7 +433,15 @@ enum branch_track {
>  	BRANCH_TRACK_EXPLICIT,
>  };
>  
> +enum rebase_setup_type {
> +	AUTOREBASE_NEVER = 0,
> +	AUTOREBASE_LOCAL,
> +	AUTOREBASE_REMOTE,
> +	AUTOREBASE_ALWAYS,
> +};
> +
>  extern enum branch_track git_branch_track;
> +extern enum rebase_setup_type autorebase;
>  
>  #define GIT_REPO_VERSION 0
>  extern int repository_format_version;
> diff --git a/config.c b/config.c
> index b0ada51..2959087 100644
> --- a/config.c
> +++ b/config.c
> @@ -487,6 +487,20 @@ int git_default_config(const char *var, const char *value)
>  		git_branch_track = git_config_bool(var, value);
>  		return 0;
>  	}
> +	if (!strcmp(var, "branch.autosetuprebase")) {
> +		if (!strcmp(value, "never"))
> +			autorebase = AUTOREBASE_NEVER;
Have this in your .git/config:
        [branch]
                autosetuprebase
and you will strcmp(NULL, "never") here.
Show 9 quoted lines
> +		else if (!strcmp(value, "local"))
> +			autorebase = AUTOREBASE_LOCAL;
> +		else if (!strcmp(value, "remote"))
> +			autorebase = AUTOREBASE_REMOTE;
> +		else if (!strcmp(value, "always"))
> +			autorebase = AUTOREBASE_ALWAYS;
> +		else
> +			die_bad_config(
> +				"Invalid value for branch.autosetupmerge");

A line slightly longer than 80-cols is better than this artificial line split, I think.

Show 9 quoted lines
> diff --git a/environment.c b/environment.c
> index 6739a3f..6fb3b97 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -38,6 +38,7 @@ int auto_crlf = 0;	/* 1: both ways, -1: only when adding git objects */
>  enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
>  unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
>  enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
> +enum rebase_setup_type autorebase = 0;

Do not initialize to 0; BSS takes care of it. Explicitly initializing to a symbolic constant, by using AUTOREBASE_NEVER, is very much Ok.

Show 10 quoted lines
> diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
> index cb5f7a4..10bb429 100755
> --- a/t/t3200-branch.sh
> +++ b/t/t3200-branch.sh
> @@ -224,4 +224,96 @@ test_expect_success 'avoid ambiguous track' '
>  	test -z "$(git config branch.all1.merge)"
>  '
>  
> +test_expect_success 'autosetuprebase local on a tracked local branch' \
> +	'git config remote.local.url . &&

Move the opening "'" to the end of the first line so you can lose backslash there and it becomes easier to read.

Dustin Sallings· May 8, 2008, 17:32 UTC · re: Junio C Hamano · lore

Re: [PATCH] Allow local branching to set up rebase by default.

	Hi, thanks for the response.
On May 7, 2008, at 9:22, Junio C Hamano wrote:
> You got no reactions, neither
> positive nor negative, partly due to this sentence, I suspect.
	I got one response from someone who said he had implemented the same  
thing in one of his branches.  That seemed to confirm the idea for  
me.  Some additional features were suggested to be built on top of  
this, but I didn't read it as necessary for proceeding.
> Please sign-off your patches (see Documentation/SubmittingPatches).
	Oh thanks, I hadn't seen this.  I read it as well as the  
CodingGuidelines document.
Show 11 quoted lines
>> +	When `never`, rebase is never automatically set to true.
>> +	When `local`, rebase is set to true for tracked branches of
>> +	other local branches.
>> +	When `remote`, rebase is set to true for tracked branches of
>> +	remote branches.
>> +	When `always`, rebase will be set to true for all tracking
>> +	branches.
>> +	This option defaults to never.
>
> How does this interact with a similarly named configuration option,
> autosetupmerge, whose settings can be false, true, and always?
	I can direct the user to the autosetupmerge config documentation  
since it also documents the flags that override its behavior.  Is this  
acceptable?
Show 18 quoted lines
>> branch.<name>.remote::
>> 	When in branch <name>, it tells `git fetch` which remote to fetch.
>> 	If this option is not given, `git fetch` defaults to remote  
>> "origin".
>
> This is not your fault, but can anybody guess what the exact command
> sequence to cause the named branch to be advanced by rebasing, only by
> reading this entry?
>
>    branch.<name>.rebase::
>            When true, rebase the branch <name> on top of the fetched  
> branch,
>            instead of merging the default branch from the default  
> remote.
>
> I can't.  Perhaps we would need "when "git pull" is run" or  
> something at
> the end.
	I'll submit this as a separate patch.
> Is this correct?
	[...]
> You might want to check how the setup_tracking() decides when to say
> remote/local in its printf().
	Oh thanks, I clearly didn't understand this and just relied on my  
tests passing by coincidence.
	I'll resubmit my patch with your recommendations, thanks.
-- 
Dustin Sallings
Junio C Hamano· May 8, 2008, 18:23 UTC · re: Dustin Sallings · lore

Re: [PATCH] Allow local branching to set up rebase by default.

Dustin Sallings <dustin@spy.net> writes:
Show 15 quoted lines
>>> +	When `never`, rebase is never automatically set to true.
>>> +	When `local`, rebase is set to true for tracked branches of
>>> +	other local branches.
>>> +	When `remote`, rebase is set to true for tracked branches of
>>> +	remote branches.
>>> +	When `always`, rebase will be set to true for all tracking
>>> +	branches.
>>> +	This option defaults to never.
>>
>> How does this interact with a similarly named configuration option,
>> autosetupmerge, whose settings can be false, true, and always?
>
> 	I can direct the user to the autosetupmerge config
> documentation since it also documents the flags that override its
> behavior.  Is this  acceptable?

Oh, it was not a request to change the description quoted above but a pure question -- asking for information. "This new configuration variable is orthogonal and does not interact with the autosetupmerge", "This takes effect only the other one decides (or --track is given from the command line) to make it track", etc. were the expected answers. It might not hurt to insert "(see branch.<name>.autosetupmerge)" before the comma in "tracks another branch," below, though...

    +branch.autosetuprebase::
    +       When a new branch is created with `git-branch` or `git-checkout`
    +       that tracks another branch, this parameter tells git to set
Dustin Sallings· May 8, 2008, 18:28 UTC · re: Junio C Hamano · lore

[PATCH] Allow tracking branches to set up rebase by default.

Change cd67e4d4 introduced a new configuration parameter that told pull to automatically perform a rebase instead of a merge. This change provides a configuration option to enable this feature automatically when creating a new branch.

If the variable branch.autosetuprebase applies for a branch that's being created, that branch will have branch.<name>.rebase set to true.

Signed-off-by: Dustin Sallings <dustin@spy.net>
---
 Documentation/config.txt |   15 +++++++
 branch.c                 |   22 ++++++++++-
 cache.h                  |    8 ++++
 config.c                 |   13 ++++++
 environment.c            |    1 +
 t/t3200-branch.sh        |   92 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 150 insertions(+), 1 deletions(-)
Show changes to 6 files +150 −1

Documentation/config.txt, branch.c, cache.h, config.c, environment.c, t/t3200-branch.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 00f089f..6413f70 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -399,6 +399,21 @@ branch.autosetupmerge::
 	done when the starting point is either a local branch or remote
 	branch. This option defaults to true.
 
+branch.autosetuprebase::
+	When a new branch is created with `git-branch` or `git-checkout`
+	that tracks another branch, this variable tells git to set
+	up pull to rebase instead of merge (see "branch.<name>.rebase").
+	When `never`, rebase is never automatically set to true.
+	When `local`, rebase is set to true for tracked branches of
+	other local branches.
+	When `remote`, rebase is set to true for tracked branches of
+	remote branches.
+	When `always`, rebase will be set to true for all tracking
+	branches.
+	See "branch.autosetupmerge" for details on how to set up a
+	branch to track another branch.
+	This option defaults to never.
+
 branch.<name>.remote::
 	When in branch <name>, it tells `git fetch` which remote to fetch.
 	If this option is not given, `git fetch` defaults to remote "origin".
diff --git a/branch.c b/branch.c
index daf862e..56e9492 100644
--- a/branch.c
+++ b/branch.c
@@ -32,6 +32,21 @@ static int find_tracked_branch(struct remote *remote, void *priv)
 	return 0;
 }
 
+static int should_setup_rebase(const struct tracking *tracking)
+{
+	switch (autorebase) {
+	case AUTOREBASE_NEVER:
+		return 0;
+	case AUTOREBASE_LOCAL:
+		return tracking->remote == NULL;
+	case AUTOREBASE_REMOTE:
+		return tracking->remote != NULL;
+	case AUTOREBASE_ALWAYS:
+		return 1;
+	}
+	return 0;
+}
+
 /*
  * This is called when new_ref is branched off of orig_ref, and tries
  * to infer the settings for branch.<new_ref>.{remote,merge} from the
@@ -69,9 +84,14 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
 	git_config_set(key, tracking.remote ?  tracking.remote : ".");
 	sprintf(key, "branch.%s.merge", new_ref);
 	git_config_set(key, tracking.src ? tracking.src : orig_ref);
-	free(tracking.src);
 	printf("Branch %s set up to track %s branch %s.\n", new_ref,
 		tracking.remote ? "remote" : "local", orig_ref);
+	if (should_setup_rebase(&tracking)) {
+		sprintf(key, "branch.%s.rebase", new_ref);
+		git_config_set(key, "true");
+		printf("This branch will rebase on pull.\n");
+	}
+	free(tracking.src);
 
 	return 0;
 }
diff --git a/cache.h b/cache.h
index d5d5dad..19f2930 100644
--- a/cache.h
+++ b/cache.h
@@ -434,7 +434,15 @@ enum branch_track {
 	BRANCH_TRACK_EXPLICIT,
 };
 
+enum rebase_setup_type {
+	AUTOREBASE_NEVER = 0,
+	AUTOREBASE_LOCAL,
+	AUTOREBASE_REMOTE,
+	AUTOREBASE_ALWAYS,
+};
+
 extern enum branch_track git_branch_track;
+extern enum rebase_setup_type autorebase;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
diff --git a/config.c b/config.c
index b0ada51..7d76986 100644
--- a/config.c
+++ b/config.c
@@ -487,6 +487,19 @@ int git_default_config(const char *var, const char *value)
 		git_branch_track = git_config_bool(var, value);
 		return 0;
 	}
+	if (value && !strcmp(var, "branch.autosetuprebase")) {
+		if (!strcmp(value, "never"))
+			autorebase = AUTOREBASE_NEVER;
+		else if (!strcmp(value, "local"))
+			autorebase = AUTOREBASE_LOCAL;
+		else if (!strcmp(value, "remote"))
+			autorebase = AUTOREBASE_REMOTE;
+		else if (!strcmp(value, "always"))
+			autorebase = AUTOREBASE_ALWAYS;
+		else
+			die_bad_config("Invalid value for branch.autosetupmerge");
+		return 0;
+	}
 
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
diff --git a/environment.c b/environment.c
index fcd1ee5..4892a30 100644
--- a/environment.c
+++ b/environment.c
@@ -38,6 +38,7 @@ int auto_crlf = 0;	/* 1: both ways, -1: only when adding git objects */
 enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
+enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
 
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index cb5f7a4..d11dd41 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -224,4 +224,96 @@ test_expect_success 'avoid ambiguous track' '
 	test -z "$(git config branch.all1.merge)"
 '
 
+test_expect_success 'autosetuprebase local on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase local &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase &&
+	git branch --track myr1 mybase &&
+	test "$(git config branch.myr1.remote)" = . &&
+	test "$(git config branch.myr1.merge)" = refs/heads/mybase &&
+	test "$(git config branch.myr1.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase always &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase2 &&
+	git branch --track myr2 mybase &&
+	test "$(git config branch.myr2.remote)" = . &&
+	test "$(git config branch.myr2.merge)" = refs/heads/mybase &&
+	test "$(git config branch.myr2.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase remote &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase3 &&
+	git branch --track myr3 mybase2 &&
+	test "$(git config branch.myr3.remote)" = . &&
+	test "$(git config branch.myr3.merge)" = refs/heads/mybase2 &&
+	! test "$(git config branch.myr3.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase never &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase4 &&
+	git branch --track myr4 mybase2 &&
+	test "$(git config branch.myr4.remote)" = . &&
+	test "$(git config branch.myr4.merge)" = refs/heads/mybase2 &&
+	! test "$(git config branch.myr4.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase local on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase local &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr5 local/master &&
+	test "$(git config branch.myr5.remote)" = local &&
+	test "$(git config branch.myr5.merge)" = refs/heads/master &&
+	! test "$(git config branch.myr5.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase never &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr6 local/master &&
+	test "$(git config branch.myr6.remote)" = local &&
+	test "$(git config branch.myr6.merge)" = refs/heads/master &&
+	! test "$(git config branch.myr6.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase remote &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr7 local/master &&
+	test "$(git config branch.myr7.remote)" = local &&
+	test "$(git config branch.myr7.merge)" = refs/heads/master &&
+	test "$(git config branch.myr7.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase remote &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr8 local/master &&
+	test "$(git config branch.myr8.remote)" = local &&
+	test "$(git config branch.myr8.merge)" = refs/heads/master &&
+	test "$(git config branch.myr8.rebase)" = true
+'
+
 test_done
-- 
1.5.5.1.100.g65b98
Junio C Hamano· May 10, 2008, 18:41 UTC · re: Dustin Sallings · lore

Re: [PATCH] Allow tracking branches to set up rebase by default.

The patch is looking better.

I'd suggest further fixes like the attached patch to address the following issues:

 - Do not ignore misconfiguration, but diagnose it.
 - die_bad_config() takes a variable name without surrounding explanatory
   text.  If you actually tested your patch and looked at the error
   message, it would have been blatantly obvious and you would have
   noticed it.  Not a good sign.
 - Test not just the success cases but failure cases; test not just
   explicitly configured cases but also default cases.

The last one is something everybody tends to forget, but is very important. It is human nature that anybody would eagerly want to demonstrate what new things their shiny new toy does, but would forget to make sure that it does not take effect when people do not want it (either saying 'never' which you do have test, which is good, or not asking for it by not setting the variable, which you didn't). You'd notice that I played lazy and added a check for only the "tracked remote" case when the new variable is left unspecified, but you might want to add tests for other variants. Also I suspect that we would want to test cases where autosetuprebase is given but autosetupmerge is not.

Another thing we might want to address is to move parsing of branch.* configuration variables out of git_default_config(). They are unnecessary for majority of commands that do not create new branches. But that would be a separate topic if we were to do so.

 config.c          |    8 +++++---
 t/t3200-branch.sh |   24 ++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)
Show changes to 2 files +29 −3

config.c, t/t3200-branch.sh

diff --git a/config.c b/config.c
index 7d76986..cf2bfd3 100644
--- a/config.c
+++ b/config.c
@@ -487,8 +487,10 @@ int git_default_config(const char *var, const char *value)
 		git_branch_track = git_config_bool(var, value);
 		return 0;
 	}
-	if (value && !strcmp(var, "branch.autosetuprebase")) {
-		if (!strcmp(value, "never"))
+	if (!strcmp(var, "branch.autosetuprebase")) {
+		if (!value)
+			return config_error_nonbool(var);
+		else if (!strcmp(value, "never"))
 			autorebase = AUTOREBASE_NEVER;
 		else if (!strcmp(value, "local"))
 			autorebase = AUTOREBASE_LOCAL;
@@ -497,7 +499,7 @@ int git_default_config(const char *var, const char *value)
 		else if (!strcmp(value, "always"))
 			autorebase = AUTOREBASE_ALWAYS;
 		else
-			die_bad_config("Invalid value for branch.autosetupmerge");
+			return error("Malformed value for %s", var);
 		return 0;
 	}
 
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index d11dd41..5cfeaa7 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -144,6 +144,18 @@ test_expect_success 'test tracking setup (non-wildcard, not matching)' \
      ! test "$(git config branch.my5.remote)" = local &&
      ! test "$(git config branch.my5.merge)" = refs/heads/master'
 
+test_expect_success 'detect misconfigured autosetuprebase' '
+	git config branch.autosetuprebase garbage &&
+	test_must_fail git branch
+'
+
+test_expect_success 'detect misconfigured autosetuprebase' '
+	git config --unset branch.autosetuprebase &&
+	echo "[branch] autosetuprebase" >>.git/config &&
+	test_must_fail git branch &&
+	git config --unset branch.autosetuprebase
+'
+
 test_expect_success 'test tracking setup via config' \
     'git config branch.autosetupmerge true &&
      git config remote.local.url . &&
@@ -316,4 +328,16 @@ test_expect_success 'autosetuprebase always on a tracked remote branch' '
 	test "$(git config branch.myr8.rebase)" = true
 '
 
+test_expect_success 'without autosetuprebase' '
+	git config --unset branch.autosetuprebase
+
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr9 local/master &&
+	test "$(git config branch.myr9.remote)" = local &&
+	test "$(git config branch.myr9.merge)" = refs/heads/master &&
+	test "z$(git config branch.myr9.rebase)" = "z"
+'
+
 test_done
Dustin Sallings· May 10, 2008, 22:36 UTC · re: Junio C Hamano · lore

Re: [PATCH] Allow tracking branches to set up rebase by default.

On May 10, 2008, at 11:41, Junio C Hamano wrote:
Show 8 quoted lines
> - die_bad_config() takes a variable name without surrounding  
> explanatory
>   text.  If you actually tested your patch and looked at the error
>   message, it would have been blatantly obvious and you would have
>   noticed it.  Not a good sign.
>
> - Test not just the success cases but failure cases; test not just
>   explicitly configured cases but also default cases.
	You're right, I didn't test misconfiguration cases.  I've updated the  
patch per your recommendations with a lot more tests and have manually  
tested the error messages to ensure they make sense.
	Does it make sense in the cases where a value is bad to list the  
valid values?  I don't see a precedent (so I don't know what format  
would be most desirable), but it might be friendly.
> Also I suspect that we would want to test cases where
> autosetuprebase is given but autosetupmerge is not.
	This code isn't so much dependent on that variable, but on the  
effects of that variable, which may be overridden by the --track and -- 
no-track parameters.  I think it'd be best to leave the effects of  
that variable in its own tests wrt tracking since this code doesn't  
kick in until after the tracking is set up.
Show 6 quoted lines
> Another thing we might want to address is to move parsing of branch.*
> configuration variables out of git_default_config().  They are  
> unnecessary
> for majority of commands that do not create new branches.  But that  
> would
> be a separate topic if we were to do so.
	I agree with this.  I tried initially to not have it be part of the  
default config parser, but it seemed a lot more disruptive, so I just  
followed autosetupmerge.
	Thanks for your input again.  New patch to follow.
-- 
Dustin Sallings
Dustin Sallings· May 10, 2008, 22:36 UTC · re: Junio C Hamano · lore

[PATCH] Allow tracking branches to set up rebase by default.

Change cd67e4d4 introduced a new configuration parameter that told pull to automatically perform a rebase instead of a merge. This change provides a configuration option to enable this feature automatically when creating a new branch.

If the variable branch.autosetuprebase applies for a branch that's being created, that branch will have branch.<name>.rebase set to true.

Signed-off-by: Dustin Sallings <dustin@spy.net>
---
 Documentation/config.txt |   15 +++
 branch.c                 |   22 ++++-
 cache.h                  |    8 ++
 config.c                 |   15 +++
 environment.c            |    1 +
 t/t3200-branch.sh        |  234 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 294 insertions(+), 1 deletions(-)
Show changes to 6 files +294 −1

Documentation/config.txt, branch.c, cache.h, config.c, environment.c, t/t3200-branch.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index a6fc5a2..217980f 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -399,6 +399,21 @@ branch.autosetupmerge::
 	done when the starting point is either a local branch or remote
 	branch. This option defaults to true.
 
+branch.autosetuprebase::
+	When a new branch is created with `git-branch` or `git-checkout`
+	that tracks another branch, this variable tells git to set
+	up pull to rebase instead of merge (see "branch.<name>.rebase").
+	When `never`, rebase is never automatically set to true.
+	When `local`, rebase is set to true for tracked branches of
+	other local branches.
+	When `remote`, rebase is set to true for tracked branches of
+	remote branches.
+	When `always`, rebase will be set to true for all tracking
+	branches.
+	See "branch.autosetupmerge" for details on how to set up a
+	branch to track another branch.
+	This option defaults to never.
+
 branch.<name>.remote::
 	When in branch <name>, it tells `git fetch` which remote to fetch.
 	If this option is not given, `git fetch` defaults to remote "origin".
diff --git a/branch.c b/branch.c
index daf862e..56e9492 100644
--- a/branch.c
+++ b/branch.c
@@ -32,6 +32,21 @@ static int find_tracked_branch(struct remote *remote, void *priv)
 	return 0;
 }
 
+static int should_setup_rebase(const struct tracking *tracking)
+{
+	switch (autorebase) {
+	case AUTOREBASE_NEVER:
+		return 0;
+	case AUTOREBASE_LOCAL:
+		return tracking->remote == NULL;
+	case AUTOREBASE_REMOTE:
+		return tracking->remote != NULL;
+	case AUTOREBASE_ALWAYS:
+		return 1;
+	}
+	return 0;
+}
+
 /*
  * This is called when new_ref is branched off of orig_ref, and tries
  * to infer the settings for branch.<new_ref>.{remote,merge} from the
@@ -69,9 +84,14 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
 	git_config_set(key, tracking.remote ?  tracking.remote : ".");
 	sprintf(key, "branch.%s.merge", new_ref);
 	git_config_set(key, tracking.src ? tracking.src : orig_ref);
-	free(tracking.src);
 	printf("Branch %s set up to track %s branch %s.\n", new_ref,
 		tracking.remote ? "remote" : "local", orig_ref);
+	if (should_setup_rebase(&tracking)) {
+		sprintf(key, "branch.%s.rebase", new_ref);
+		git_config_set(key, "true");
+		printf("This branch will rebase on pull.\n");
+	}
+	free(tracking.src);
 
 	return 0;
 }
diff --git a/cache.h b/cache.h
index 7fb8f33..3442130 100644
--- a/cache.h
+++ b/cache.h
@@ -434,7 +434,15 @@ enum branch_track {
 	BRANCH_TRACK_EXPLICIT,
 };
 
+enum rebase_setup_type {
+	AUTOREBASE_NEVER = 0,
+	AUTOREBASE_LOCAL,
+	AUTOREBASE_REMOTE,
+	AUTOREBASE_ALWAYS,
+};
+
 extern enum branch_track git_branch_track;
+extern enum rebase_setup_type autorebase;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
diff --git a/config.c b/config.c
index b0ada51..cf2bfd3 100644
--- a/config.c
+++ b/config.c
@@ -487,6 +487,21 @@ int git_default_config(const char *var, const char *value)
 		git_branch_track = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "branch.autosetuprebase")) {
+		if (!value)
+			return config_error_nonbool(var);
+		else if (!strcmp(value, "never"))
+			autorebase = AUTOREBASE_NEVER;
+		else if (!strcmp(value, "local"))
+			autorebase = AUTOREBASE_LOCAL;
+		else if (!strcmp(value, "remote"))
+			autorebase = AUTOREBASE_REMOTE;
+		else if (!strcmp(value, "always"))
+			autorebase = AUTOREBASE_ALWAYS;
+		else
+			return error("Malformed value for %s", var);
+		return 0;
+	}
 
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
diff --git a/environment.c b/environment.c
index fcd1ee5..4892a30 100644
--- a/environment.c
+++ b/environment.c
@@ -38,6 +38,7 @@ int auto_crlf = 0;	/* 1: both ways, -1: only when adding git objects */
 enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
+enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
 
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index cb5f7a4..8d87686 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -224,4 +224,238 @@ test_expect_success 'avoid ambiguous track' '
 	test -z "$(git config branch.all1.merge)"
 '
 
+test_expect_success 'autosetuprebase local on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase local &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase &&
+	git branch --track myr1 mybase &&
+	test "$(git config branch.myr1.remote)" = . &&
+	test "$(git config branch.myr1.merge)" = refs/heads/mybase &&
+	test "$(git config branch.myr1.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase always &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase2 &&
+	git branch --track myr2 mybase &&
+	test "$(git config branch.myr2.remote)" = . &&
+	test "$(git config branch.myr2.merge)" = refs/heads/mybase &&
+	test "$(git config branch.myr2.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase remote &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase3 &&
+	git branch --track myr3 mybase2 &&
+	test "$(git config branch.myr3.remote)" = . &&
+	test "$(git config branch.myr3.merge)" = refs/heads/mybase2 &&
+	! test "$(git config branch.myr3.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase never &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase4 &&
+	git branch --track myr4 mybase2 &&
+	test "$(git config branch.myr4.remote)" = . &&
+	test "$(git config branch.myr4.merge)" = refs/heads/mybase2 &&
+	! test "$(git config branch.myr4.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase local on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase local &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr5 local/master &&
+	test "$(git config branch.myr5.remote)" = local &&
+	test "$(git config branch.myr5.merge)" = refs/heads/master &&
+	! test "$(git config branch.myr5.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase never on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase never &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr6 local/master &&
+	test "$(git config branch.myr6.remote)" = local &&
+	test "$(git config branch.myr6.merge)" = refs/heads/master &&
+	! test "$(git config branch.myr6.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase remote on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase remote &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr7 local/master &&
+	test "$(git config branch.myr7.remote)" = local &&
+	test "$(git config branch.myr7.merge)" = refs/heads/master &&
+	test "$(git config branch.myr7.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase always on a tracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	git config branch.autosetuprebase remote &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr8 local/master &&
+	test "$(git config branch.myr8.remote)" = local &&
+	test "$(git config branch.myr8.merge)" = refs/heads/master &&
+	test "$(git config branch.myr8.rebase)" = true
+'
+
+test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' '
+	git config --unset branch.autosetuprebase &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --track myr9 local/master &&
+	test "$(git config branch.myr9.remote)" = local &&
+	test "$(git config branch.myr9.merge)" = refs/heads/master &&
+	test "z$(git config branch.myr9.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase unconfigured on a tracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	git branch mybase10 &&
+	git branch --track myr10 mybase2 &&
+	test "$(git config branch.myr10.remote)" = . &&
+	test "$(git config branch.myr10.merge)" = refs/heads/mybase2 &&
+	test "z$(git config branch.myr10.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase unconfigured on untracked local branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr11 mybase2 &&
+	test "z$(git config branch.myr11.remote)" = z &&
+	test "z$(git config branch.myr11.merge)" = z &&
+	test "z$(git config branch.myr11.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase unconfigured on untracked remote branch' '
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr12 local/master &&
+	test "z$(git config branch.myr12.remote)" = z &&
+	test "z$(git config branch.myr12.merge)" = z &&
+	test "z$(git config branch.myr12.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase never on an untracked local branch' '
+	git config branch.autosetuprebase never &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr13 mybase2 &&
+	test "z$(git config branch.myr13.remote)" = z &&
+	test "z$(git config branch.myr13.merge)" = z &&
+	test "z$(git config branch.myr13.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase local on an untracked local branch' '
+	git config branch.autosetuprebase local &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr14 mybase2 &&
+	test "z$(git config branch.myr14.remote)" = z &&
+	test "z$(git config branch.myr14.merge)" = z &&
+	test "z$(git config branch.myr14.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase remote on an untracked local branch' '
+	git config branch.autosetuprebase remote &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr15 mybase2 &&
+	test "z$(git config branch.myr15.remote)" = z &&
+	test "z$(git config branch.myr15.merge)" = z &&
+	test "z$(git config branch.myr15.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase always on an untracked local branch' '
+	git config branch.autosetuprebase always &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr16 mybase2 &&
+	test "z$(git config branch.myr16.remote)" = z &&
+	test "z$(git config branch.myr16.merge)" = z &&
+	test "z$(git config branch.myr16.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase never on an untracked remote branch' '
+	git config branch.autosetuprebase never &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr17 local/master &&
+	test "z$(git config branch.myr17.remote)" = z &&
+	test "z$(git config branch.myr17.merge)" = z &&
+	test "z$(git config branch.myr17.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase local on an untracked remote branch' '
+	git config branch.autosetuprebase local &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr18 local/master &&
+	test "z$(git config branch.myr18.remote)" = z &&
+	test "z$(git config branch.myr18.merge)" = z &&
+	test "z$(git config branch.myr18.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase remote on an untracked remote branch' '
+	git config branch.autosetuprebase remote &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr19 local/master &&
+	test "z$(git config branch.myr19.remote)" = z &&
+	test "z$(git config branch.myr19.merge)" = z &&
+	test "z$(git config branch.myr19.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase always on an untracked remote branch' '
+	git config branch.autosetuprebase always &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	git branch --no-track myr20 local/master &&
+	test "z$(git config branch.myr20.remote)" = z &&
+	test "z$(git config branch.myr20.merge)" = z &&
+	test "z$(git config branch.myr20.rebase)" = z
+'
+
+test_expect_success 'detect misconfigured autosetuprebase (bad value)' '
+	git config branch.autosetuprebase garbage &&
+	test_must_fail git branch
+'
+
+test_expect_success 'detect misconfigured autosetuprebase (no value)' '
+	git config --unset branch.autosetuprebase &&
+	echo "[branch] autosetuprebase" >> .git/config &&
+	test_must_fail git branch &&
+	git config --unset branch.autosetuprebase
+'
+
 test_done
-- 
1.5.5.1.179.g0325e.dirty
Dustin Sallings· May 8, 2008, 18:28 UTC · re: Junio C Hamano · lore

[PATCH] Doc: Mention branch.<name>.rebase applies to "git pull"

Signed-off-by: Dustin Sallings <dustin@spy.net>
---
 Documentation/config.txt |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
Show changes to Documentation/config.txt +2 −1
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 6413f70..44bd20b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -441,7 +441,8 @@ branch.<name>.mergeoptions::
 
 branch.<name>.rebase::
 	When true, rebase the branch <name> on top of the fetched branch,
-	instead of merging the default branch from the default remote.
+	instead of merging the default branch from the default remote when
+	"git pull" is run.
 	*NOTE*: this is a possibly dangerous operation; do *not* use
 	it unless you understand the implications (see linkgit:git-rebase[1]
 	for details).
-- 
1.5.5.1.100.g65b98
Dustin Sallings· May 7, 2008, 06:01 UTC · lore

Re: [PATCH] Allow local branching to set up rebase by default.

On Apr 29, 2008, at 14:49, Dustin Sallings wrote:
	[a patch]
	I haven't seen any activity related to this in a week.  This  
functionality is interesting to my coworkers and a small sampling I've  
polled.  Does it require any kind of cleanup, will it be completely  
rejected, or should I just be more patient?  :)
-- 
Dustin Sallings
Junio C Hamano· May 7, 2008, 15:19 UTC · re: Dustin Sallings · lore

Re: [PATCH] Allow local branching to set up rebase by default.

Dustin Sallings <dustin@spy.net> writes:
Show 8 quoted lines
> On Apr 29, 2008, at 14:49, Dustin Sallings wrote:
>
> 	[a patch]
>
> 	I haven't seen any activity related to this in a week.  This
> functionality is interesting to my coworkers and a small sampling I've
> polled.  Does it require any kind of cleanup, will it be completely
> rejected, or should I just be more patient?  :)

What happened probably is that nobody on the list found it interesting. I do not offhand recall what the patch was about.

You cited <02471C27-C99D-43E7-BC58-50F2B86ED159@spy.net> as the original message that your message is a reply to, but I do not seem to be able to get it via mail archives. I am guessing you meant this one:

    Message-ID: <1209502182-39800-1-git-send-email-dustin@spy.net>
    http://news.gmane.org/gmane.comp.version-control.git/80732

← back to recent threads