rebase script

28 views
Skip to first unread message

Anthony

unread,
Dec 11, 2009, 9:12:47 AM12/11/09
to Repo and Gerrit Discussion
I have to rebase almost every change I make several times, so I was
thinking about making a script that would parse out the URL to go to
the direct, make a temporary branch, rebase, and reupload since this
has become incredibly tedious doing all the time.

Is there a good way I could grab that information out without editing
Gerrit (because I don't have access to the source no one of the
servers we use, and I don't like keeping patches around when
updating). I haven't looked through Gerrit's source enough to know how
its structured yet for displaying pages, and you can't just wget
gerrit-path/<change number> since it uses xhr to load everything.

Or any other suggestions on this topic?

Shawn Pearce

unread,
Dec 11, 2009, 5:22:42 PM12/11/09
to repo-d...@googlegroups.com
If you have the change number, the pull command can be computed on
the fly. E.g. look at the gerrit-cherry-pick shell script that
is available via `scp -p 29418 server:bin/gerrit-cherry-pick`,
it makes the refs/changes/ string on the fly:

to_ref() {
case $1 in
*/*)
change_id=${1%%/*}
patchset_id=${1##*/}
;;
*)
change_id=$1
patchset_id=1
;;
esac

hash=$(($change_id % 100))
case $hash in
[0-9]) hash="0$hash" ;;
esac

echo "refs/changes/$hash/$change_id/$patchset_id"
}

So use it like:

git fetch ssh://URL/to/project `to_ref 42`

Anthony

unread,
Dec 14, 2009, 11:04:04 PM12/14/09
to Repo and Gerrit Discussion
Thanks..seems easy enough for the reference part. I suppose I can just
require they be in the path that the replace should be done.

I was thinking that it could just create a temporary branch like
TMP_CHANGE_$id, fetch into it, cherry-pick, rebase, and upload --
replace. The only other remaining difficulty is telling repo where to
put it. Is there any clean way to do that part without modifying repo
or using expect?

Something like this (haven't run this and anyone reading
shouldn't...just showing concept):

ref=""
to_ref() {
case $1 in
*/*)
change_id=${1%%/*}
patchset_id=${1##*/}
;;
*)
change_id=$1
patchset_id=1
;;
esac

hash=$(($change_id % 100))
case $hash in
[0-9]) hash="0$hash" ;;
esac

ref="refs/changes/$hash/$change_id/$patchset_id"
}

# this is a bit hacky too...but easier than getting an ini parser in
bash
server=`cat .git/config | grep url | sed -e 's/.*ssh:\/\///' | sed -e
's/\/.*//'`
path=`pwd | sed -e 's#$ANDROID_BUILD_TOP/##'`
to_ref $1

branch="TMP_CHANGE_$1"
git branch -D $branch 2>/dev/null
repo start $branch

git fetch ssh://$server/$path $ref
git fetch FETCH_HEAD
git rebase m/<need something generic here .. maybe grab it out of
manifest.xml>
repo upload --replace .

On Dec 11, 4:22 pm, Shawn Pearce <s...@google.com> wrote:

Shawn Pearce

unread,
Dec 15, 2009, 11:11:38 AM12/15/09
to repo-d...@googlegroups.com
Anthony <m.b...@gmail.com> wrote:
> I was thinking that it could just create a temporary branch like
> TMP_CHANGE_$id, fetch into it, cherry-pick, rebase, and upload --
> replace. The only other remaining difficulty is telling repo where to
> put it. Is there any clean way to do that part without modifying repo
> or using expect?

There isn't a way to know which branch the change is meant for
without looking at the web interface, or doing a JSON-RPC request
to get the change data. So the best you can do is guess, or have
the user give the name to you as an argument.

> # this is a bit hacky too...but easier than getting an ini parser in
> bash
> server=`cat .git/config | grep url | sed -e 's/.*ssh:\/\///' | sed -e
> 's/\/.*//'`

Yuck. Next time use git config and its many options.

> path=`pwd | sed -e 's#$ANDROID_BUILD_TOP/##'`

Oh, I see. You use this only to form the URL later. Don't.

> branch="TMP_CHANGE_$1"
> git branch -D $branch 2>/dev/null
> repo start $branch
>
> git fetch ssh://$server/$path $ref
> git fetch FETCH_HEAD
> git rebase m/<need something generic here .. maybe grab it out of
> manifest.xml>
> repo upload --replace .

Yuck. This might be a bit cleaner, since it also makes use of
the manifest metadata like repo would:

remote=`repo forall . -c echo \$REPO_REMOTE`
branch=`repo forall . -c echo \$REPO_RREV`
rebase=`repo forall . -c echo \$REPO_LREV`

git fetch $remote $ref
git checkout $rebase
git cherry-pick FETCH_HEAD
git push $remote HEAD:refs/for/$branch

Reply all
Reply to author
Forward
0 new messages