views:

142

answers:

4

I have two branches that are different enough that rebasing seems to not work -- or I don't know how to do it.

I have a "public" branch with a bunch of files removed (using filter-branch). Even though most of the commits match up in terms of deltas, the commit ids are all different. I've tried quite a few methods to pull changes from my dev branch to my public branch... I find it hard to believe it can do what I want it to do -- but I suspect I just don't know how to do it. In any case, this works fine, but seems wrong.

git checkout dev
git format-patch --stdout last_sync_tag > catchup.mbox
git checkout public
git am catchup.mbox
git --skip # talks about a missing file
git --skip # talks about a missing file
git --skip # talks about a missing file

Any tips or suggestions, which will probably include not filter-branching out files you don't want on the public branch (though, how do you then get rid of them?), are welcome.

My tree(s) look more or less like this:

dev: a-b-c-d-e-f-g-h-i-j-k
pub: t-u-v-w-x

t ≅ a, u ≅ c, v ≅ d, w ≅ e, x ≅ g. i,j,k are new patches I'd like to move over.

checkout pub
rebase --onto pub i  # I really expected this to work
+1  A: 
Pat Notz
I like this. I was cherry-picking by hand a bit. this is like the next logical step.
jettero
I based a cute little git command after this. Works great, thanks.
jettero
A: 

Well if I don't want a fileit lands in .gitignore. Probably it is the config not real code so it doesn't need tracking at all.

Maciej Piechotka
two problems ... git clean -dfx kills the files you're ignoring and two, the files do need tracking, just not on the public branch.
jettero
+1  A: 

Because you've used "filter-branch" you're going to have to help git find the correct commit to perform the rebase onto.

I'm going to guess here, but presumably you have an 'almost' common commit which has two versions, the head of your public branch and the place on your dev branch that this commit corresponds to (un-filtered). Call the public head commit <PH> and the dev commit that this corresponds to (before filtering) <DevPH>.

with the dev branch checked out, you want to do something like this:

git rebase --onto <PH> <DevPH>

This tells rebase to take the patches introduced by each commit since <DevPH> on the current branch and to apply these commits to <PH>. I think that this is what you need.

Edit:

Your update to the question shows that h is equivalent to the head of the public stream on the dev branch and that you want to transplant everything from here onwards on the dev branch onto the public branch. If so the command is

git rebase --onto pub h
Charles Bailey
That's what I woulda thought would work, but it doesn't. I made a new branch called blarg, reset --hard a few commits back and tried git rebase -v --onto blarg 80d79e3, where 80d79e3 is the correct commit on the dev branch. It just says: First, rewinding head to replay your work on top of it... Fast-forwarded blarg to blarg. with -v, it shows it's trying to rebase blarg's HEAD onto blarg.
jettero
If it's fast-forwarding then you are just rebasing back onto the branch that you were already on. You need to specify a commit from the other branch as the argument for --onto. I'm sure that you can do what you want with rebase, but without looking at your tree it is difficult to point to which commits you need to specify where. Can you put more details of the common commits and the new branch heads and how they relate in your question?
Charles Bailey
+1  A: 

Do you regularly maintain the files on your dev branch that aren't on public? Or are they just hanging around?

If you don't tend to make changes to them, and you're OK with rewriting the history a bit, what you could do is arrange to have them created as a single commit based on your public branch; and merge that back into public but with "-s ours" to stop them actually getting in. (previous answer about git merge -s ours)

Something like:

git checkout -b dev public
git am create-dev-only-files.patch
git checkout public
git merge -s ours dev
git checkout dev
# write more dev patches...
git checkout public
git merge dev
# and this should merge in the patches without bringing in the
#  dev-only files

So if you then made subsequent changes on your dev branch and merged them into public, if you're not changing those files that aren't on public, everything else will simply apply. But if the set of files you want to suppress on public changes, this could be tricky. You could try to prevent it by adding a pre-commit hook to unstage particular files before starting any commit on the public branch, for example.

araqnid