cg-branch-switch and local branches
PATCH 1/1 cg-branch-switch and local branches
Make origin a symbolic link to the origin branch. Make master a symbolic link to the local branch or
a file for an unnamed branch.
Add cg-branch-switch to switch branches.
--- Makefile | 3 + cg-Xnormid | 2 + cg-branch-add | 19 +++++++++ cg-branch-switch | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ cg-clone | 32 ++++++++++++---- cg-commit | 11 ++++- cg-merge | 3 + cg-pull | 14 +++++-- 8 files changed, 177 insertions(+), 14 deletions(-)
Makefile +2 -1
@@ -55,7 +55,8 @@ PROG= git-update-cache git-diff-files SCRIPT= commit-id tree-id parent-id cg-add cg-admin-lsobj cg-admin-uncommit \ cg-branch-add cg-branch-ls cg-cancel cg-clone cg-commit cg-diff \ cg-export cg-help cg-init cg-log cg-ls cg-merge cg-mkpatch cg-patch \ - cg-pull cg-restore cg-rm cg-seek cg-status cg-tag cg-tag-ls cg-update + cg-pull cg-restore cg-rm cg-seek cg-status cg-tag cg-tag-ls cg-update \ + cg-branch-switch LIB_SCRIPT=cg-Xlib cg-Xmergefile cg-Xnormid
cg-Xnormid +2 -0
@@ -16,6 +16,8 @@ id="$1" +[ -L $_git/refs/heads/$id ] && +id=$(readlink $_git/refs/heads/$id | sed 's@/@#@') repo=$(echo $id | cut -d '#' -f 1) (echo $repo | egrep -qv '[^a-zA-Z0-9_.@!:-]') || \ die "name contains invalid characters"
cg-branch-add +19 -0
@@ -1,8 +1,11 @@ #!/usr/bin/env bash # # Add new branch to the GIT repository. +# Or create local branch in the GIT repository. # Copyright (c) Petr Baudis, 2005 # +# Adding a new branch +# ------------------- # Takes the branch name and source location as parameters. # After you add a branch, you can `cg-pull` it whenever you want and # it will keep your objects database in sync with it. Its latest
@@ -29,6 +32,22 @@ # $ cg-branch-add repo-testing rsync://host/path/repo.git#testing # # and refer to it as 'repo-testing' anytime later. +# +# Creating a local branch +# ----------------------- +# Takes the local branch name and origin branch as parameters. +# +# After you create a local branch, you can `cg-branch-switch` it whenever you +# want and you will be able to work on your local branch. Its {latest,origin} +# commit is accessible as `.git/refs/heads/{master,origin}` (or - more +# conveniently - as `$(commit-id {master,origin})`). +# For example, to make a diff between your origin and your current tree, do: +# +# $ cg-diff -r origin +# +# The origin specifier is a name of a branch added with cg-branch-add, +# followed with an optional fragment part, which identifies a alternative +# branch inside of the repository. USAGE="cg-branch-add BRANCH_NAME LOCATION"
cg-branch-switch new file +107 -0
107 lines not on this page · raw message
cg-clone +25 -7
@@ -6,10 +6,10 @@ # This is like cg-init, but it will create a new directory where it will do # the checkout. # -# Takes a parameter specifying the location of the source repository and an -# optional second parameter specifying the destination. If the second -# parameter is omitted, the basename of the source repository is used as the -# destination. +# Takes two parameter specifying the name and location of the source +# repository, an optional third parameter specifying name of the local branch +# (defaults to an unnamed branch) and an optional fourth parameter specifying +# the destination (defaults to the basename of the source repository). # # OPTIONS # -------
@@ -17,7 +17,7 @@ # Clone in the current directory instead of creating a new one. # Specifying both -s and a desination directory makes no sense . -USAGE="cg-clone [-s] LOCATION [DESTDIR]" +USAGE="cg-clone [-s] NAME LOCATION [LOCALNAME [DESTDIR]]" . ${COGITO_LIB}cg-Xlib
@@ -27,9 +27,16 @@ if [ "$1" = "-s" ]; then same_dir=1 fi +name=$1 && shift location=$1 [ "$location" ] || usage location=${location%/} +if [ $location = $1 ] ; then + branch=$(echo $location | cut -d '#' -f 2 -s) + location=$(echo $location | cut -d '#' -f 1) +fi +shift +localbranch=$1 destdir=$2 if [ "$destdir" ]; then
@@ -45,6 +52,8 @@ else location="$location" fi +[ "$branch" ] && location=$location#$branch + if [ ! "$same_dir" ]; then [ -e "$dir" ] && die "$dir/ already exists" mkdir "$dir" || exit $?
@@ -54,6 +63,15 @@ else fi trap "rm -rf $dir" SIGTERM EXIT -cg-init $location || exit $? +git-init-db +cg-branch-add $name $location +cg-pull $name || die "pull failed" +if [ "$localbranch" ] ; then + cg-branch-add $localbranch $name + cg-branch-switch $localbranch +else + cg-branch-switch $name +fi +echo "Master and origin branches are:" +cg-branch-switch trap "" SIGTERM EXIT -echo "Cloned to $dir/ (origin $location available as branch \"origin\")"
cg-commit +9 -2
@@ -144,9 +144,16 @@ if [ "$merging" ]; then repo=$(echo $sym | cut -d '#' -f 1) branch=$(echo $sym | cut -d '#' -f 2 -s) uri=$(cat $_git/branches/$repo) + urirepo=$(echo $uri | cut -d '#' -f 1) uribranch=$(echo $uri | cut -d '#' -f 2 -s) - [ -z "$uribranch" ] && [ -n "$branch" ] && - [ "$branch" != master ] && uri=${uri}#$branch + if [ -e $_git/branches/$urirepo ]; then + # local branch + uri="$sym" + else + # remote branch + [ -z "$uribranch" ] && [ -n "$branch" ] && + [ "$branch" != master ] && uri=${uri}#$branch + fi [ "$uri" ] || uri="$sym" echo "$uri" >>$LOGMSG [ "$msgs" ] && echo "$uri"
cg-merge +2 -1
@@ -42,7 +42,8 @@ fi [ "$1" ] || usage branchname="$1" branch=$(commit-id "$branchname") || exit 1 - +[ -L $_git/refs/heads/$branchname ] && +branchname=$(readlink $_git/refs/heads/$branchname| sed 's@/@#@') [ "$base" ] || base=$(git-merge-base "$head" "$branch") [ "$base" ] || die "unable to automatically determine merge base"
cg-pull +11 -3
@@ -19,16 +19,24 @@ USAGE="cg-pull [-a] [BRANCH_NAME]" [ "$1" == "-a" ] && all=yes && shift name=$1 && shift -[ "$name" ] || { [ -s $_git/refs/heads/origin ] && name=origin; } +if [ -z "$name" ] && [ -f $_git/branches/origin ]; then + #Convert the old layout 2005/06 + mv $_git/branches/origin $_git/branches/original + branch=$(cat $_git/branches/original | cut -s -d '#' -f 2) + branch=${branch:-master} + [ -f $_git/refs/heads/origin -o -d $_git/refs/heads/origin ] && + rm -rf $_git/refs/heads/origin && + ln -s original/$branch $_git/refs/heads/origin +fi +[ "$name" ] || name=$(readlink $_git/refs/heads/origin | sed 's@/@#@') [ "$name" ] || die "where to pull from?" repo=$(echo $name | cut -d '#' -f 1) repobranch=$(echo $name | cut -s -d '#' -f 2) -uri=$(cat "$_git/branches/$name" 2>/dev/null) || die "unknown branch: $name" +uri=$(cat "$_git/branches/$repo" 2>/dev/null) || die "unknown branch: $name" if echo "$uri" | grep -q '#'; then [ -z "$repobranch" ] && repobranch=$(echo $uri | cut -d '#' -f 2) - rembranch=$(echo $uri | cut -d '#' -f 2) uri=$(echo $uri | cut -d '#' -f 1) fi repobranch=${repobranch:-master}
Hi,
after reading it I think I have to explain it better.
And first I have to say that this patch depends on my patches in the thread "[COGITO PATCH] Heads and tags in subdirectories". But the logic does not depend on it, I think :)
Suppose I want to make some modifications to the cogito. So I do:
cg-clone cogito rsync://rsync.kernel.org/pub/scm/cogito/cogito.git
the first argument been the name I've gave to this repositori. Now I can do the changes/commits in the usual way. But I want to work in two differents patches, named dirs and switch, so I do:
cg-branch-add dirs cogito
cg-branch-add switch cogito
Now I have to local branches with their respective names, and the origin been the cogito branch for both (but it can be different).
If I want to work on the dirs branch I do:
cg-branch-switch dirs
an the same for switch. In each case I can do a:
cg-merge origin
and merge their respective origin (in this case is the same).
If I want to work directly in cogito, I can do:
cg-branch-switch cogito
and work in the usual way. If the cogito repository have a branche called cogito2 I could do:
cg-branch-switch cogito#cogito2
in the case I've already pulled this branch.
Internally it is:
Local branches
--------------
The master file is always a link:
master -> ${localbranch}
The content of $_git/branches/${localbranch} is the original branch of local branch. The cases and the corresponding origin links are:
1a.- name : a name of an external repository
$branch corresponding to the definition origin -> $name/$branch
1b.- name#branch : optionally with a branch
origin -> $name/$branch
2 .- name : a name of another local branch
$branch corresponding to the definition origin -> $name/$branch
Local unnamed branches
----------------------
The master file is a regular file and the origin link only has the cases 1a and 1b where the $name is name of the local branch.
Here it is un update version fixing some bugs. It depends on my update version of the "[COGITO PATCH] Heads and tags in subdirectories" patch.
Santi
Makefile | 3 + cg-Xnormid | 2 + cg-branch-add | 19 +++++++++ cg-branch-switch | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ cg-clone | 32 ++++++++++++---- cg-commit | 17 +++++++- cg-merge | 3 + cg-pull | 24 ++++++++---- 8 files changed, 189 insertions(+), 18 deletions(-)
Makefile +2 -1
@@ -55,7 +55,8 @@ PROG= git-update-cache git-diff-files SCRIPT= commit-id tree-id parent-id cg-add cg-admin-lsobj cg-admin-uncommit \ cg-branch-add cg-branch-ls cg-cancel cg-clone cg-commit cg-diff \ cg-export cg-help cg-init cg-log cg-ls cg-merge cg-mkpatch cg-patch \ - cg-pull cg-restore cg-rm cg-seek cg-status cg-tag cg-tag-ls cg-update + cg-pull cg-restore cg-rm cg-seek cg-status cg-tag cg-tag-ls cg-update \ + cg-branch-switch LIB_SCRIPT=cg-Xlib cg-Xmergefile cg-Xnormid
cg-Xnormid +2 -0
@@ -16,6 +16,8 @@ id="$1" +[ -L $_git/refs/heads/$id ] && +id=$(readlink $_git/refs/heads/$id | sed 's@/@#@') repo=$(echo $id | cut -d '#' -f 1) (echo $repo | egrep -qv '[^a-zA-Z0-9_.@!:-]') || \ die "name contains invalid characters"
cg-branch-add +19 -0
@@ -1,8 +1,11 @@ #!/usr/bin/env bash # # Add new branch to the GIT repository. +# Or create local branch in the GIT repository. # Copyright (c) Petr Baudis, 2005 # +# Adding a new branch +# ------------------- # Takes the branch name and source location as parameters. # After you add a branch, you can `cg-pull` it whenever you want and # it will keep your objects database in sync with it. Its latest
@@ -29,6 +32,22 @@ # $ cg-branch-add repo-testing rsync://host/path/repo.git#testing # # and refer to it as 'repo-testing' anytime later. +# +# Creating a local branch +# ----------------------- +# Takes the local branch name and origin branch as parameters. +# +# After you create a local branch, you can `cg-branch-switch` it whenever you +# want and you will be able to work on your local branch. Its {latest,origin} +# commit is accessible as `.git/refs/heads/{master,origin}` (or - more +# conveniently - as `$(commit-id {master,origin})`). +# For example, to make a diff between your origin and your current tree, do: +# +# $ cg-diff -r origin +# +# The origin specifier is a name of a branch added with cg-branch-add, +# followed with an optional fragment part, which identifies a alternative +# branch inside of the repository. USAGE="cg-branch-add BRANCH_NAME LOCATION"
cg-branch-switch new file +107 -0
107 lines not on this page · raw message
cg-clone +25 -7
@@ -6,10 +6,10 @@ # This is like cg-init, but it will create a new directory where it will do # the checkout. # -# Takes a parameter specifying the location of the source repository and an -# optional second parameter specifying the destination. If the second -# parameter is omitted, the basename of the source repository is used as the -# destination. +# Takes two parameter specifying the name and location of the source +# repository, an optional third parameter specifying name of the local branch +# (defaults to an unnamed branch) and an optional fourth parameter specifying +# the destination (defaults to the basename of the source repository). # # OPTIONS # -------
@@ -17,7 +17,7 @@ # Clone in the current directory instead of creating a new one. # Specifying both -s and a desination directory makes no sense . -USAGE="cg-clone [-s] LOCATION [DESTDIR]" +USAGE="cg-clone [-s] NAME LOCATION [LOCALNAME [DESTDIR]]" . ${COGITO_LIB}cg-Xlib
@@ -27,9 +27,16 @@ if [ "$1" = "-s" ]; then same_dir=1 fi +name=$1 && shift location=$1 [ "$location" ] || usage location=${location%/} +if [ $location = $1 ] ; then + branch=$(echo $location | cut -d '#' -f 2 -s) + location=$(echo $location | cut -d '#' -f 1) +fi +shift +localbranch=$1 destdir=$2 if [ "$destdir" ]; then
@@ -45,6 +52,8 @@ else location="$location" fi +[ "$branch" ] && location=$location#$branch + if [ ! "$same_dir" ]; then [ -e "$dir" ] && die "$dir/ already exists" mkdir "$dir" || exit $?
@@ -54,6 +63,15 @@ else fi trap "rm -rf $dir" SIGTERM EXIT -cg-init $location || exit $? +git-init-db +cg-branch-add $name $location +cg-pull $name || die "pull failed" +if [ "$localbranch" ] ; then + cg-branch-add $localbranch $name + cg-branch-switch $localbranch +else + cg-branch-switch $name +fi +echo "Master and origin branches are:" +cg-branch-switch trap "" SIGTERM EXIT -echo "Cloned to $dir/ (origin $location available as branch \"origin\")"
cg-commit +15 -2
@@ -143,10 +143,23 @@ if [ "$merging" ]; then for sym in $(cat $_git/merging-sym); do repo=$(echo $sym | cut -d '#' -f 1) branch=$(echo $sym | cut -d '#' -f 2 -s) + if [ -L $_git/refs/heads/$sym ]; then + uri=$(readlink $_git/refs/heads/$sym) + repo=$(echo $uri | cut -d '#' -f 1) + [ -z "$branch" ] && + branch=$(echo $uri | cut -d '#' -f 2 -s) + fi uri=$(cat $_git/branches/$repo) + urirepo=$(echo $uri | cut -d '#' -f 1) uribranch=$(echo $uri | cut -d '#' -f 2 -s) - [ -z "$uribranch" ] && [ -n "$branch" ] && - [ "$branch" != master ] && uri=${uri}#$branch + if [ -e $_git/branches/$urirepo ]; then + # local branch + uri="$repo" + else + # remote branch + [ -z "$uribranch" ] && [ -n "$branch" ] && + [ "$branch" != master ] && uri=${uri}#$branch + fi [ "$uri" ] || uri="$sym" echo "$uri" >>$LOGMSG [ "$msgs" ] && echo "$uri"
cg-merge +2 -1
@@ -42,7 +42,8 @@ fi [ "$1" ] || usage branchname="$1" branch=$(commit-id "$branchname") || exit 1 - +[ -L $_git/refs/heads/$branchname ] && +branchname=$(readlink $_git/refs/heads/$branchname| sed 's@/@#@') [ "$base" ] || base=$(git-merge-base "$head" "$branch") [ "$base" ] || die "unable to automatically determine merge base"
cg-pull +17 -7
@@ -19,18 +19,28 @@ USAGE="cg-pull [-a] [BRANCH_NAME]" [ "$1" == "-a" ] && all=yes && shift name=$1 && shift -[ "$name" ] || { [ -s $_git/refs/heads/origin ] && name=origin; } +if [ -z "$name" ] && [ -f $_git/branches/origin ]; then + #Convert the old layout 2005/06 + mv $_git/branches/origin $_git/branches/original + branch=$(cat $_git/branches/original | cut -s -d '#' -f 2) + branch=${branch:-master} + [ -f $_git/refs/heads/origin -o -d $_git/refs/heads/origin ] && + rm -rf $_git/refs/heads/origin && + ln -s original/$branch $_git/refs/heads/origin +fi +[ "$name" ] || name=$(readlink $_git/refs/heads/origin | sed 's@/@#@') [ "$name" ] || die "where to pull from?" repo=$(echo $name | cut -d '#' -f 1) repobranch=$(echo $name | cut -s -d '#' -f 2) -uri=$(cat "$_git/branches/$name" 2>/dev/null) || die "unknown branch: $name" -if echo "$uri" | grep -q '#'; then - [ -z "$repobranch" ] && repobranch=$(echo $uri | cut -d '#' -f 2) - rembranch=$(echo $uri | cut -d '#' -f 2) - uri=$(echo $uri | cut -d '#' -f 1) -fi +uri=$(cat "$_git/branches/$repo" 2>/dev/null) || die "unknown branch: $name" +urirepo=$(echo $uri | cut -d '#' -f 1) +uribranch=$(echo $uri | cut -d '#' -f 2 -s) + +[ -e $_git/branches/$urirepo ] && die "Local branches are already pulled" + +repobranch=${repobranch:-$uribranch} repobranch=${repobranch:-master} branch=$repo/$repobranch [ "$all" ] && repobranch=
Hi,
I have realized that it was overcomplicated and against the common practice of having .git/HEAD pointing to the current branch, as I've just seen on a git-switch-branch by Jeff.
But the only thing I miss now is the origin handling.
Sorry for the noise.
Santi