Last active
May 10, 2021 03:49
-
-
Save foriequal0/2a3bb342b14dc8fa5ac042ae3e3c6784 to your computer and use it in GitHub Desktop.
git-scratch
This file contains hidden or 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 |
Author
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)
When the issue management is streamlined, and the team is sufficiently grown and mature so the roles of members are divided enough, then the member can focus on a single topic.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 switchandgit rebasecannot be neglected.So, I gave up to fork a topic branch early. I dump all the commits on a
scratchbranch 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.scratchbranch.scratchbranch.scratchonto 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