Last active
March 10, 2022 17:18
-
-
Save PEZ/f8d1c9d1184efa9e6ea929e7da69efce to your computer and use it in GitHub Desktop.
Zsh functions to help rebasing git branches safely
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
# Previous branch is `baz` | |
~/Foo(bar|✔) % rebobl - | |
logging to: /var/folders/t5/gqxhj8pd6p9_tnvy6sbtmy480000gn/T/rebob.YJJZirAY | |
rebob: No branch given, checking REBOBS in /Users/pez/.my-configs/rebob_config.zshrc | |
rebob: rebob /Users/pez/Foo:bar on - | |
rebob: pulling?: false | |
rebob: Created: .rebobing | |
Saved working directory and index state WIP on bar: 17fa37c Add baz | |
rebob: Stashed -u (.rebobing stashed) | |
Current branch bar is up to date. | |
rebob: Rebased on: baz | |
Already up to date! | |
rebob: Popped the stack (.rebobing is back) | |
rebob: Removed: .rebobing |
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
# rebob = rebase branch on branch | |
function echo2_and_log() { | |
log=$1 | |
msg=$2 | |
log_msg="$(date +"%Y-%m-%dT%H:%M:%S") ${msg}" | |
echo "rebob: ${msg}" >&2 | |
echo ${log_msg} >>${log} | |
} | |
function _rebob() { | |
start_path_branch="$(git rev-parse --show-toplevel):$(git branch --show-current)" || { echo "Error. Are you really in a git repo? Aborting." >&2 ; return 1 } | |
log=$(mktemp -t rebob) | |
echo logging to: ${log} >&2 | |
if [[ -z "$1" ]]; then | |
echo2_and_log ${log} "No branch given. Aborting" | |
return 1 | |
else | |
rebob_on_branch=$1 | |
fi | |
echo2_and_log ${log} "rebob ${rebob_on_branch} on ${start_path_branch}" | |
echo2_and_log ${log} "pulling?: $2" | |
{ date > .rebobing && echo2_and_log ${log} "Created: .rebobing" } || { echo2_and_log ${log} "Creating .rebobing failed. Aborting." ; return 1; } | |
{ git stash -u && echo2_and_log ${log} "Stashed -u (.rebobing stashed)" } || { echo2_and_log ${log} "stash failed. Aborting." ; return 1; } | |
if [ "$2" = true ]; then | |
{ git checkout ${rebob_on_branch} && echo2_and_log ${log} "Checked out: ${rebob_on_branch}" } || { echo2_and_log ${log} "checkout ${rebob_on_branch} failed. Aborting." ; return 1; } | |
{ git pull && echo2_and_log ${log} "Pulled" } || { echo2_and_log ${log} "pull failed. Aborting." ; return 1; } | |
{ git checkout - && echo2_and_log ${log} "Checkout back on: ${start_path_branch}" } || { echo2_and_log ${log} "checkout ${start_path_branch} failed. Aborting." ; return 1; } | |
fi | |
{ git rebase ${rebob_on_branch} && echo2_and_log ${log} "Rebased on: ${rebob_on_branch}" } || { echo2_and_log ${log} "rebase ${rebob_on_branch} failed. Aborting." ; return 1; } | |
{ git stash pop -q && echo2_and_log ${log} "Popped the stack (.rebobing is back)" } || { echo2_and_log ${log} "stash pop failed. Aborting." ; return 1; } | |
{ rm .rebobing && echo2_and_log ${log} "Removed: .rebobing" } || { echo2_and_log ${log} "rm .rebobing failed" ; return 1; } | |
return 0 | |
} | |
function rebob() { | |
if [[ ! -z "$1" ]]; then | |
_rebob $1 true | |
else | |
_rebob "" true | |
fi | |
} | |
# rebobl = rebase branch on branch locally (w/o pull) | |
function rebobl() { | |
if [[ ! -z "$1" ]]; then | |
_rebob $1 false | |
else | |
_rebob "" false | |
fi | |
} | |
# remaster - rebob special case =) | |
function remaster() { | |
rebob master | |
} |
After some weeks of using this I declare huge success! 🎉
The rebob_config.zshrc
(see ealier revisions if you are curious) was a YAGNI, though. Not used it at all because rebob -
covers my use case perfectly. My use case is building a library in a monorepo where I am also implementing it in one of the projects. The library is being merged to master continuously from various branch-A
s, while the PoC implementation is yet-to-be-merged at all, just living in a PR of its own, based on bramch-B
.
So when some branch-A
is ready for PR I do:
$ remaster
$ git push
$ git checkout -b branch-next-A
$ git checkout `branch-B`
$ rebobl -
$ git push -f
Then do new work where some of it is committed to branch-next-A
and some to branch-B
, and the cycle continues.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To use: source
rebob.zshrc
.