threads / patch / 5007

patchPer branch properties for pull and fetch

Subject: [PATCH] Per branch properties for pull and fetch

## tl;dr

7 messages between Jul 27, 2006 and Jul 27, 2006. Diffs are folded; open one to read it.

replies: 6people: 3as markdown or json

Santi Béjar· Jul 27, 2006, 08:14 UTC · lore

It allows to specify on a per branch basis the following: .- default repository to fetch .- default branches to merge on a per repository basis .- default pull.{octopus,twohead}

So if you have this in the config:
[branch "my"]
	remote=yours
	merge=master
	merge=our from theirs
	merge=mine from .
and you are in the branch "my":
"git pull": fetch the remote yours and merge the branch master.
"git pull theirs": fetch the remote theirs and merge the branch our.
"git pull .": merge the branch mine from the local repository.
---
 Documentation/config.txt |   14 +++++++++++
 git-fetch.sh             |   13 ++++++----
 git-parse-remote.sh      |   57 ++++++++++++++++++++++++++++++++++++++++++++++
 git-pull.sh              |   29 ++++++++++++++++++++---
 4 files changed, 104 insertions(+), 9 deletions(-)
Show changes to 4 files +104 −9

Documentation/config.txt, git-fetch.sh, git-parse-remote.sh, git-pull.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 465eb13..f12b595 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -116,6 +116,20 @@ apply.whitespace::
 	Tells `git-apply` how to handle whitespaces, in the same way
 	as the '--whitespace' option. See gitlink:git-apply[1].
 
+branch.<name>.remote::
+	When in branch <name>, it tells `git-fetch` which remote to fetch.
+
+branch.<name>.merge::
+	When in branch <name>, it tells `git-pull` to merge this remote
+	branch of the repository branch.<name>.remote. To specify a different
+	remote repository use the from `<branch> from <repo>`.
+
+branch.<name>.octopus::
+	When in branch <name>, the same as pull.octopus.
+
+branch.<name>.twohead::
+	When in branch <name>, the same as pull.twohead.
+
 diff.color::
 	When true (or `always`), always use colors in patch.
 	When false (or `never`), never.  When set to `auto`, use
diff --git a/git-fetch.sh b/git-fetch.sh
index c2eebee..8129d8a 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -68,11 +68,13 @@ done
 
 case "$#" in
 0)
-	test -f "$GIT_DIR/branches/origin" ||
-		test -f "$GIT_DIR/remotes/origin" ||
-			git-repo-config --get remote.origin.url >/dev/null ||
-				die "Where do you want to fetch from today?"
-	set origin ;;
+	curr_branch=$(git-symbolic-ref HEAD)
+	curr_branch=${curr_branch##refs/heads/}
+	origin=$(git-repo-config --get "branch.$curr_branch.remote")
+	origin=${origin:-origin}
+	test -n "$(get_remote_url $origin)" ||
+		die "Where do you want to fetch from today?"
+	set $origin ;;
 esac
 
 remote_nick="$1"
@@ -446,3 +448,4 @@ case ",$update_head_ok,$orig_head," in
 	fi
 	;;
 esac
+echo $remote_nick >"$GIT_DIR/FETCH_REMOTE"
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 187f088..fe6c713 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -209,3 +209,60 @@ resolve_alternates () {
 		esac
 	done
 }
+
+get_head_for_remote_branch () {
+	if [ "$1" == "." ];
+	then
+		git-rev-parse $2 2>/dev/null||
+			die "error: no such ref $2"
+		return
+	fi
+	data_source=$(get_data_source "$1")
+	case "$data_source" in
+	config)
+		refspec=$(git-repo-config --get "remote.$1.fetch" ^$2:) ;;
+	branches)
+		remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
+		case "$remote_branch" in '') remote_branch=master ;; esac
+		[ $remote_branch == $2 ] &&
+		refspec="refs/heads/${remote_branch}:refs/heads/$1"
+		;;
+	remotes)
+		refspec=$(grep "^Pull: $2:" $GIT_DIR/remotes/$1)
+		refspec=${refspec##Pull: }
+		;;
+	*)
+		die "internal error: get-head_for_remote_branch" ;;
+	esac
+	[ "$refspec" ] || die "Branch $2 does not exist in the repository: $1."
+	git-rev-parse $(expr "z$refspec" : 'z[^:]*:\(.*\)')
+}
+
+get_heads_to_merge_in_branch () {
+ 	case "$#" in
+	2)
+		default=$(git repo-config --get-all "branch.$1.remote")
+		: >"$GIT_DIR/HEADS_TO_MERGE"
+		git repo-config --get-all "branch.$1.merge" |
+		while read ref ; do
+			case $ref in
+			?*' 'from' '?*)
+				remote=$(expr "z$ref" : 'z.* from \(.*\)')
+				branch=$(expr "z$ref" : 'z\(.*\) from .*');;
+			*)
+				remote=$default
+				branch=$ref;;
+			esac
+			[ "$remote" != "$2" ] && continue
+			headm=$(get_head_for_remote_branch $remote $branch) || exit 1
+			echo $headm
+			remoteurl=$(get_remote_url $remote)
+			remoteurl_1=$(expr "z$remoteurl" : 'z\(.*\)\.git/*$') &&
+				remoteurl=$remoteurl_1
+			echo "$headm		branch '$branch' of $remoteurl" \
+				>>"$GIT_DIR/HEADS_TO_MERGE"
+		done
+		;;
+	*) exit 1
+	esac
+}
diff --git a/git-pull.sh b/git-pull.sh
index f380437..467d9c0 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -7,6 +7,7 @@ # Fetch one or more remote refs and merg
 USAGE='[-n | --no-summary] [--no-commit] [-s strategy]... [<fetch-options>] <repo> <head>...'
 LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
 . git-sh-setup
+. git-parse-remote
 
 strategy_args= no_summary= no_commit= squash=
 while case "$#,$1" in 0) break ;; *,-*) ;; *) break ;; esac
@@ -47,6 +48,8 @@ done
 orig_head=$(git-rev-parse --verify HEAD) || die "Pulling into a black hole?"
 git-fetch --update-head-ok --reflog-action=pull "$@" || exit 1
 
+curr_branch=$(git-symbolic-ref HEAD)
+curr_branch=${curr_branch##refs/heads/}
 curr_head=$(git-rev-parse --verify HEAD)
 if test "$curr_head" != "$orig_head"
 then
@@ -70,9 +73,18 @@ to recover.'
 
 fi
 
-merge_head=$(sed -e '/	not-for-merge	/d' \
-	-e 's/	.*//' "$GIT_DIR"/FETCH_HEAD | \
-	tr '\012' ' ')
+remote=$(cat "$GIT_DIR/FETCH_REMOTE")
+merge_head=$(get_heads_to_merge_in_branch "$curr_branch" "$remote" ) || exit
+
+if [ -n "$merge_head" ];
+then
+	merge_name=$(git-fmt-merge-msg <"$GIT_DIR/HEADS_TO_MERGE") || exit
+else
+	merge_head=$(sed -e '/	not-for-merge	/d' \
+		-e 's/	.*//' "$GIT_DIR"/FETCH_HEAD | \
+		tr '\012' ' ')
+	merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit
+fi
 
 case "$merge_head" in
 '')
@@ -85,6 +97,11 @@ case "$merge_head" in
 	then
 		strategy_default_args="-s $var"
 	fi
+	var=`git-repo-config --get branch.$curr_branch.octopus`
+	if test -n "$var"
+	then
+		strategy_default_args="-s $var"
+	fi
 	;;
 *)
 	var=`git-repo-config --get pull.twohead`
@@ -92,6 +109,11 @@ case "$merge_head" in
         then
 		strategy_default_args="-s $var"
 	fi
+	var=`git-repo-config --get branch.$curr_branch.twohead`
+	if test -n "$var"
+        then
+		strategy_default_args="-s $var"
+	fi
 	;;
 esac
 
@@ -101,7 +123,6 @@ case "$strategy_args" in
 	;;
 esac
 
-merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit
 git-merge "--reflog-action=pull $*" \
 	$no_summary $no_commit $squash $strategy_args \
 	"$merge_name" HEAD $merge_head
-- 
1.4.2.rc2.g1728
Martin Waitz· Jul 27, 2006, 08:55 UTC · re: Santi Béjar · lore

Re: [PATCH] Per branch properties for pull and fetch

hoi :)
On Thu, Jul 27, 2006 at 10:14:45AM +0200, Santi Béjar wrote:
Show 11 quoted lines
> It allows to specify on a per branch basis the following:
> .- default repository to fetch
> .- default branches to merge on a per repository basis
> .- default pull.{octopus,twohead}
> 
> So if you have this in the config:
> [branch "my"]
> 	remote=yours
> 	merge=master
> 	merge=our from theirs
> 	merge=mine from .

could we default the to-be-merged branch to "remotes/$remote/$branch" if that exists?. That could make life a lot easier when using clone --use-separate-remote.

-- 
Martin Waitz
Santi· Jul 27, 2006, 09:40 UTC · re: Martin Waitz · lore

Re: [PATCH] Per branch properties for pull and fetch

2006/7/27, Martin Waitz <tali@admingilde.org>:
Show 18 quoted lines
> hoi :)
>
> On Thu, Jul 27, 2006 at 10:14:45AM +0200, Santi Béjar wrote:
> > It allows to specify on a per branch basis the following:
> > .- default repository to fetch
> > .- default branches to merge on a per repository basis
> > .- default pull.{octopus,twohead}
> >
> > So if you have this in the config:
> > [branch "my"]
> >       remote=yours
> >       merge=master
> >       merge=our from theirs
> >       merge=mine from .
>
> could we default the to-be-merged branch to "remotes/$remote/$branch" if
> that exists?. That could make life a lot easier when using
> clone --use-separate-remote.

I would prefer to change git-clone and git-branch to write the full config. And I'll do this if this or someting like this is accepted.

  Santi
Santi· Jul 27, 2006, 10:06 UTC · re: Santi · lore

Re: [PATCH] Per branch properties for pull and fetch

2006/7/27, Santi <sbejar@gmail.com>:
Show 23 quoted lines
> 2006/7/27, Martin Waitz <tali@admingilde.org>:
> > hoi :)
> >
> > On Thu, Jul 27, 2006 at 10:14:45AM +0200, Santi Béjar wrote:
> > > It allows to specify on a per branch basis the following:
> > > .- default repository to fetch
> > > .- default branches to merge on a per repository basis
> > > .- default pull.{octopus,twohead}
> > >
> > > So if you have this in the config:
> > > [branch "my"]
> > >       remote=yours
> > >       merge=master
> > >       merge=our from theirs
> > >       merge=mine from .
> >
> > could we default the to-be-merged branch to "remotes/$remote/$branch" if
> > that exists?. That could make life a lot easier when using
> > clone --use-separate-remote.
>
> I would prefer to change git-clone and git-branch to write the full
> config. And I'll do this if this or someting like this is accepted.
>

On the other hand, my patch changes the behaviour only when explicitly configured, and your proposed default would change the behaviour even without changes to the config.

Santi
Martin Waitz· Jul 27, 2006, 12:02 UTC · re: Santi · lore

Re: [PATCH] Per branch properties for pull and fetch

hoi :)
On Thu, Jul 27, 2006 at 12:06:34PM +0200, Santi wrote:
> >> could we default the to-be-merged branch to "remotes/$remote/$branch" if
> >> that exists?. That could make life a lot easier when using
> >> clone --use-separate-remote.
> On the other hand, my patch changes the behaviour only when explicitly
> configured, and your proposed default would change the behaviour even
> without changes to the config.
that is correct.

The current default is to always use the remote's master branch, right? What do others think: does it make sense to default to the same branchname on the remote side?

It could make life a bit easier if you want to synchronize several topic branches between different sites.

-- 
Martin Waitz
Santi· Jul 27, 2006, 13:10 UTC · re: Martin Waitz · lore

Re: [PATCH] Per branch properties for pull and fetch

> The current default is to always use the remote's master branch, right?
No.

For .git/remotes/ remotes it defaults to the first Pull line. For .git/branches/ remotes if defaults to master, but you can specify another branch.

Santi
Matthias Lederhofer· Jul 27, 2006, 20:26 UTC · re: Martin Waitz · lore

Re: [PATCH] Per branch properties for pull and fetch

Martin Waitz <tali@admingilde.org> wrote:
> The current default is to always use the remote's master branch, right?
> What do others think: does it make sense to default to the same
> branchname on the remote side?

I like the separate-remote option too and having one simple command that pulls the changes from the correct remote branch would be nice. It should do something like $ git pull ${1:-origin} $(git-symbolic-ref HEAD | cut -d / -f 3-)

← back to recent threads