Created
January 27, 2023 23:43
-
-
Save evinism/6abd2d4940e64aa71d6d110b74667ae8 to your computer and use it in GitHub Desktop.
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
# GitKit | |
## Experimental git branch management tool | |
function gk(){ | |
if [ $# -eq 0 ]; then | |
echo "Usage: gk <command> [args]" | |
echo "Commands:" | |
echo " branch <branch> - create a new branch off the current branch" | |
echo " parent [branch] - get the parent of the current branch or the given branch" | |
echo " children [branch] - get the children of the current branch or the given branch" | |
echo " upchain [branch] - list the chain of branches from the current branch or the given branch" | |
echo " downchain [branch] - list the chain of branches from the current branch or the given branch" | |
echo " chain [branch] - list both upchain and downchain in order" | |
echo " evolve - rebase all children on top of the current branch, recursively" | |
echo " up - move one branch up the chain" | |
echo " down - move one branch down the chain" | |
echo " setparent <parent> - set the parent of the current branch" | |
echo " markmerged - mark the current branch as merged" | |
return 1 | |
fi | |
local command=gk_$1 | |
shift | |
if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then | |
echo "ERROR: Not in a git repository" | |
return 1 | |
fi | |
$command $@ | |
} | |
function gk_branch(){ | |
if [ $# -eq 0 ]; then | |
echo "Usage: gk branch <branch>" | |
return 1 | |
fi | |
local dependent=$1 | |
local base=$(git rev-parse --abbrev-ref HEAD) | |
# If branch has already been created, fail | |
if git show-ref --verify --quiet refs/heads/$dependent; then | |
echo "Branch $dependent already exists" | |
return 1 | |
fi | |
git checkout -b $dependent | |
git config branch.$dependent.description "$base" | |
} | |
function gk_parent(){ | |
local branch | |
if [ $# -eq 0 ]; then | |
branch=$(git rev-parse --abbrev-ref HEAD) | |
else | |
branch=$1 | |
fi | |
git config branch.$branch.description | |
} | |
function gk_children(){ | |
local base_branch | |
if [ $# -eq 0 ]; then | |
base_branch=$(git rev-parse --abbrev-ref HEAD) | |
else | |
base_branch=$1 | |
fi | |
git for-each-ref --format='%(refname:short)' refs/heads | while read b; do | |
if [ "$(gk_parent $b)" = "$base_branch" ]; then | |
echo $b | |
fi | |
done | |
} | |
function listchain_helper(){ | |
local branch=$1 | |
echo $branch | |
local parent=$(gk_parent $branch) | |
if [ -n "$parent" ]; then | |
listchain_helper $parent | |
fi | |
} | |
function gk_upchain(){ | |
local branch | |
if [ $# -eq 0 ]; then | |
branch=$(git rev-parse --abbrev-ref HEAD) | |
else | |
branch=$1 | |
fi | |
listchain_helper $branch | |
echo "-- end of chain --" | |
} | |
function gk_downchain(){ | |
local branch | |
if [ $# -eq 0 ]; then | |
branch=$(git rev-parse --abbrev-ref HEAD) | |
else | |
branch=$1 | |
fi | |
local children=$(gk_children $branch) | |
# if multiple children, print out a special message | |
echo $branch | |
if [ $(echo $children | wc -w) -gk 1 ]; then | |
echo "[multiple children]" | |
elif [ -n "$children" ]; then | |
gk_downchain $children | |
else | |
echo "-- end of chain --" | |
fi | |
} | |
function gk_chain(){ | |
local branch | |
if [ $# -eq 0 ]; then | |
branch=$(git rev-parse --abbrev-ref HEAD) | |
else | |
branch=$1 | |
fi | |
# reverse the order of the upchain, appending a star as the last character on the last line | |
gk_upchain $branch | tac | sed '$ s/$/*/' | |
gk_downchain $branch | tail -n +2 | |
} | |
function gk_evolve(){ | |
# rebase all children on top of the current branch, recursively | |
local branch=$(git rev-parse --abbrev-ref HEAD) | |
local children=$(gk_children $branch) | |
for child in $children; do | |
echo "Rebasing $child on $branch" | |
git checkout $child | |
git rebase $branch | |
gk_evolve | |
done | |
git checkout $branch | |
} | |
function gk_up(){ | |
# Move one branch up the chain | |
local branch=$(git rev-parse --abbrev-ref HEAD) | |
local parent=$(gk_parent $branch) | |
if [ -n "$parent" ]; then | |
git checkout $parent | |
else | |
echo "No parent branch" | |
fi | |
} | |
function gk_down(){ | |
# Move one branch down the chain | |
local branch=$(git rev-parse --abbrev-ref HEAD) | |
local children=$(gk_children $branch) | |
# If multiple children, fail | |
if [ $(echo $children | wc -w) -gt 1 ]; then | |
echo "Multiple children branches" | |
return 1 | |
fi | |
if [ -n "$children" ]; then | |
git checkout $children | |
else | |
echo "No child branch" | |
fi | |
} | |
function gk_setparent(){ | |
# Set the parent of the current branch | |
local branch=$(git rev-parse --abbrev-ref HEAD) | |
local parent=$1 | |
if [ -z "$parent" ]; then | |
echo "Usage: gk setparent <parent>" | |
return 1 | |
fi | |
git config branch.$branch.description $parent | |
} | |
function gk_markmerged(){ | |
# Mark the current branch as merged | |
local branch=$(git rev-parse --abbrev-ref HEAD) | |
# If git disagrees that it's merged, fail | |
if ! git branch --merged main | grep -q $branch; then | |
echo "Branch $branch is not merged" | |
return 1 | |
fi | |
local children=$(gk_children $branch) | |
for child in $children; do | |
git checkout $child | |
gk_setparent main | |
done | |
git checkout $branch | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment