Last active
May 10, 2021 03:49
-
-
Save foriequal0/2a3bb342b14dc8fa5ac042ae3e3c6784 to your computer and use it in GitHub Desktop.
git-scratch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
## Requires: (optional) git-sync | |
set -euo pipefail | |
OPTS_SPEC="\ | |
$0 [<branch-name>] [<options>] | |
An opinionated git workflow for random walker. | |
-- | |
h,help show the help | |
r,remote!=remote remote name | |
b,base!=branch remote base branch name | |
" | |
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" | |
REMOTE=$(git remote | head -n 1) | |
BASE= | |
while [ $# -gt 0 ]; do | |
case "$1" in | |
-r|--remote) REMOTE=$2; shift 2 ;; | |
-b|--base) BASE=$2; shift 2 ;; | |
--) shift; break ;; | |
*) >&2 echo "Unexpected option: $1"; exit 1; | |
esac | |
done | |
if [ -z "$REMOTE" ]; then | |
>&2 echo "No remote" | |
exit -1 | |
fi | |
if [ -n "$BASE" ]; then | |
BASE="refs/remotes/$REMOTE/$BASE" | |
else | |
BASE=$(git symbolic-ref "refs/remotes/$REMOTE/HEAD" || true) | |
fi | |
if [ -z "$BASE" ]; then | |
REMOTE_HEAD=$(git remote show "$REMOTE" | sed -n 's/\s*HEAD branch: //p') | |
>&2 echo "Retry after setting default default base branch for $REMOTE:" | |
>&2 echo " git remote set-head $REMOTE --auto" | |
exit -1 | |
fi | |
git_scratch() { | |
git switch scratch || git switch -c scratch | |
local MERGE_BASE=$(git merge-base HEAD "$BASE") | |
local BASE_REF=$(git rev-parse "$BASE") | |
if [ "$MERGE_BASE" != "$BASE_REF" ]; then | |
git rebase --autostash -i "$BASE" | |
fi | |
} | |
git_scratch_fork() { | |
local BRANCH="$1" | |
git switch scratch | |
git switch -c "$BRANCH" | |
git rebase --autostash -i "$BASE" | |
git push -u "$REMOTE" "$BRANCH" | |
} | |
if which git-sync > /dev/null; then | |
git sync | |
else | |
git remote update "$REMOTE" | |
fi | |
if [ $# -eq 0 ]; then | |
git_scratch | |
else | |
git_scratch_fork "$1" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There are so many git branch workflow. From classic Git flow to lightweight Github flow, and their derivatives that match every team's deploy strategies. They exist because they have pros, but they are not the silver bullet. So I've made another git branch management strategy called 'Git scratch flow' (and it is not a silver bullet, too)
However, I'm an only member of a team. Also, I'm not skilled at issue management, and I'm still discovering the problem domain while programming the product. Naturally, I have to handle multiple topics simultaneously, undergo trial and error, and do programming like Infinite monkey, and it looks like Brownian motion. It is hard to pick a topic in priori and come up with an appropriate name in this case. The overhead of
git switch
andgit rebase
cannot be neglected.So, I gave up to fork a topic branch early. I dump all the commits on a
scratch
branch as small as possible. And keep committing until there are enough random walks commits that can make a meaningful group of commits. Now, you prepare a PR.scratch
branch.scratch
branch.scratch
onto the base from time to time.The script is a shortcut to this workflow. You can get back to work with
git scratch
, and prepare a PR withgit scratch <topic name>
. That's it. I even aliased it asgit s