Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

git workflow across forced updates



This is my workflow to handle forced updates in the git repository
conversion as smoothly as regular updates:

1. When I start working on a change, say for PR 12345, I create two
   branches with a short name describing the change:

        git branch pr12345-mumblefix-base origin/trunk
        git checkout -b pr12345-mumblefix pr12345-mumblefix-base

2. I commit some changes on the branch with `git commit -i' to
   interactively select the hunks to commit so I can keep separate
   functional (or non-functional) changes.

   Sometimes I want to amend a previous commit, so I find the commit
   hash, say 1234abcd, and make a fixup commit:

        git commit --fixup 1234abcd

   This makes a magic commit message `fixup! <title of 1234abcd>'.
   Then from time to time I rebase to apply the fixups:

        git rebase -i --autosquash pr12345-mumblefix-base

3. Sometimes I push changes from the branch to the CVS repository with
   git cvsexportcommit:

        git cvsexportcommit -c -p -v -w ~/cvs/src 1234abcd

   If the change is near an RCS id line ($NetBSD: ...$), it is
   sometimes necessary to omit `-p' so the patch is allowed to apply
   with smaller context, but I manually eyeball it before I do that,
   just in case.

4. When I want to update the repository, I use the attached script to
   create a new branch pr12345-mumblefix-v2 on a new base
   pr12345-mumblefix-v2-base with all the same commits:

        /path/to/git-update.sh pr12345-mumblefix origin/trunk

   or, next time, to make pr12345-mumblefix-v3:

        /path/to/git-update.sh pr12345-mumblefix-v2 origin/trunk

   Of course, there might be merge conflicts to resolve.  Sometimes if
   I've already committed changes git will figure that out; sometimes
   git won't figure it out but it's just a matter of skipping a commit
   with `git rebase --skip'.

   It's not highly polished -- if you want to give up on resolving the
   merge conflicts, you can do `git rebase --abort', but git-update.sh
   won't clean up the branches it already created.  Nevertheless, it's
   been very handy for my development needs.

   (You can also put it in your PATH and then say `git update' instead
   of `/path/to/git-update.sh'.  Not sure if git plans to add a
   standard `git update' command, though.)

5. When I'm done and I've pushed all the changes to CVS and the branch
   is now empty on update, so pr12345-mumblefix-vN is the same as
   pr12345-mumblefix-vN-base, I rename all the branches to be
   closed/pr12345-mumblefix-vN and closed/pr12345-mumblefix-vN-base.
   Not perfect but easy to ignore in `git branch' output.

   (You can also just delete the branches, if the proposition of
   deleting history doesn't make your skin crawl like it does for me.)
#!/bin/sh

# Copyright (c) 2023 Taylor R. Campbell
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
# NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -Ceu

run()
{
	echo '#' "$@"
	${DRY_RUN+:} "$@"
}

oldbranch=$1
newbase=${2-origin/trunk}

case $oldbranch in
*-v[0-9] | *-v[0-9][0-9])
	prefix=${1%-v*}
	oldversion=${1##*-v}
	newversion=$((oldversion + 1))
	;;
*)
	prefix=$1
	newversion=2
	;;
esac
newbranch=${prefix}-v${newversion}

if git rev-parse --verify --quiet ${newbranch}-base >/dev/null; then
	printf >&2 'git-update: new base %s already exists\n' ${newbranch}-base
	exit 1
fi

if git rev-parse --verify --quiet ${newbranch} >/dev/null; then
	printf >&2 'git-update: new branch %s already exists\n' ${newbranch}
	exit 1
fi

if ! run git diff --stat --exit-code; then
	printf >&2 'git-update: dirty working tree, aborting\n'
	exit 1
fi

if ! run git diff --cached --stat --exit-code; then
	printf >&2 'git-update: dirty staging area, aborting\n'
	exit 1
fi

run git branch ${newbranch}-base $newbase
run git branch $newbranch $oldbranch
run git rebase --onto ${newbranch}-base ${oldbranch}-base $newbranch


Home | Main Index | Thread Index | Old Index