Reputation: 3931
For this project I'm working on, we're using a fairly standard git rebase workflow. That is, we'll do all of our work in a feature
branch. After a feature is ready to be tested, someone else will:
git checkout master
git merge feature
We also have a stable
branch, which is basically a less bleeding-edge copy of master
. After the changes in master
have been thoroughly tested by others, someone will then:
git checkout stable
git merge master
The problem I'm having is the following situation:
master
has many new commits compared to stable
, since a new feature has just been pushed out for testing.master
are not at all ready to be merged into stable
.stable
, and needs to be fixed right away.I can't simply add the bugfix to stable
and then rebase master
on top of it, as others have checked out master
. I can't add the bugfix to master
and then merge it into stable
, because master
contains commits which aren't at all ready for use. And, finally, I don't want to just add the bugfix to the end of both stable
and master
, because this would make the next git checkout stable && git merge master
break.
How can I adjust my workflow to accommodate this situation? I'd like to avoid duplicating commits (i.e., stable
ending up with the "same commit" twice, with different commit hashes), or merge commits.
Currently, since this situation doesn't come up very often, I just rebase master
onto stable
and make sure everyone else that has it checked out is aware. I'm wondering if there's a more clean way to achieve this, however.
Upvotes: 3
Views: 1745
Reputation: 60443
Here's an easy way, or I hope it will seem easy after a bit of study, that avoids the merge commits.
From text and comments I see you're doing the marching-ants trick with master
and stable
, where the only operation (at least usually) permitted on either of them is a fast-forward merge:
...--X--...S stable
\
m--...--M master
\
f--...--F feature
What I suggest follows, bear with me when you get to the ugly-looking result of this first part:
git checkout master -B m-temp # let's do this with nonce names at first
git revert X
# (maybe **amend** the commit to what X should have been here)
git checkout stable -B s-temp
git cherry-pick m-temp
git checkout feature -B f-temp
git cherry-pick m-temp
producing:
...--X--...S---X'' s-temp
\
m--...--M---X' m-temp
\
f--...--F---X''' f-temp
and all your branches have exactly one fix for X on them. This looks like a mess, but
notice what a fast-forward merge really is. When it's time to catch stable up to master, you can do it correctly with either of
git checkout s-temp # the slow way
git reset --hard @{1} # . (reset one commit from s-temp, i.e. to S)
git merge m-temp # .
or get the exact same effect with:
git checkout -B s-temp m-temp # exactly the same, without the rube goldberg
each of those producing:
X'' <-- discarded cherry-pick of X'
/
...--X--...S---m--...--M---X' m-temp s-temp
\
f--...--F---X''' f-temp
... and your branches still all have exactly one fix for X. When it's time to fast-forward master just do likewise, leaving X' also discarded and X''' the sole X fix in your history, or you can have your feature-branch devs rebase onto X' and discard their own X'''s
Git has a 'description' config item for branches. Here's something useful to put in a post-checkout hook:
cat >>.git/hooks/post-checkout <<\EOF
#!/bin/sh
#
# if there's a stored note about this checkout, show it:
# $3 = 1 for a full branch checkout
if branch=`git symbolic-ref --short -q HEAD` && test $3 = 1; then
git config --get-all branch.$branch.description
fi
EOF
chmod +x .git/hooks/post-checkout
and then when you want to remind yourself of something,
git config --add branch.stable.description \
"reset to commit c0ffee before merging master"
which makes cherry-picking any master fixes you want about as easy as can be. When you want the note gone,
git config --unset branch.stable.description c0ffee
makes all the notes matching regex c0ffee
go away.
Upvotes: 2
Reputation: 48418
Make the bug fix off of stable
, then merge it into both stable
and master
.
git checkout -b bugfix stable
# Make and commit changes
git checkout stable
git merge bugfix
git checkout master
git merge bugfix
That way, there's only one commit (or set of commits) with the bug fix in it so there shouldn't be conflicts when you merge master
into stable
later.
Upvotes: 6