git-refresh: Automatically rebase current branch onto master
Different people have different workflows with git. Mine is pretty simple.
- Branch from master
- Hack, hack, hack,
git stash; git checkout master; git pull --ff-only; git checkout $branch; git rebase master; git stash pop
- Goto step 2 until done
That step 3 is pretty damned annoying. I try to keep branches short-lived, but I often rebase onto master to ensure a clean merge. Thus, I wrote git-refresh
. It does step 3 for me. However, my git-fu is sorely lacking (and my bash scripting ain't great either), so suggestions for improving this code are welcome.
#!/bin/bash
# vim: filetype=sh
prog=$(basename $0)
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" == "master" ]; then
echo Already on master. Exiting.
exit 0
fi
need_to_stash=$(git status --porcelain|grep -v '^??')
if [[ $need_to_stash ]]; then
git stash save "stashed by $prog"
fi
git checkout master
git fetch -p
git pull --ff-only
git checkout $branch
if [[ $(git rebase master) ]]; then
if [[ $need_to_stash ]]; then
git stash pop
fi
else
echo git rebase failed.
if [[ $need_to_stash ]]; then
echo You have changes stashed by $prog
fi
fi
Mine is similar but seems less painful, I tend to avoid stash and keep partial changes with the branch which I'll clean up with a rebase interactive...
More often than not I'll rebase -i and clean up as I go, but certainly for the last rebase before merge/pull request.
I'm a big fan of git up. I guess it won't help in your case, but the magic stashing and unstashing behaviour is really nice.
The implicit question raised by Mr. Anonymous is valid, though: why use a feature branch if you never ever commit? You could at least consider baby-step-commits that you later interactively rebase into a giant-leap-for-mankind-commit.
confuseAcat: I do merge back to master. And my branch names often look like this:
feature-description-$ticket
feature-description-$ticket-2
feature-description-$ticket-3
feature-description-$ticket-4
The trailing number means "part X". I merge tiny pieces back to master all of them time, but there are enough people working on the code base where I'm consulting that even having a branch a few minutes old means someone else has likely pushed :)
git status --porcelain -uno
should be the same as yourgit status --porcelain|grep -v '^??'
the long form of-uno
is--untracked-files=no
if your not into the whole brevity thing.Like a few of the other commenters my workflow makes keeping long running changes in a stash unattractive. I often keep my work in progress that's not ready for distribution to the team in a working branch with many small commits and then
git merge --squash
the changes into a single commit.Being able to specify a different base branch name than 'master' might be handy.
Git v1.8.4 added the
--autostash
option togit rebase
. Using yourmaster
as an intermediate branch is not really necessary; you can useorigin/master
instead. Combine those together and you can dogit fetch && git rebase --autostash origin/master
.+1 nnutter. You can use your -p, too:
git fetch -p && git rebase --autostash origin/master