Starting with
hack---F1----M1----F2 (feature)
/ /
C1-----C2----C3 (master)
I would like to end up with
hack---F1----M1----F2 (feature)
/ /
C1-----C2----C3---F1'---F2' (master)
So far the best I have is
git checkout feature
git checkout -b temp
git rebase -i --onto master hack temp
* Big drawback: manually remove the merged-in C2 and C3 from list of commits *
git checkout master
git merge temp
git branch -d temp
I hope someone can answer even though this is a dubious workflow.
By default, a rebase will simply drop merge commits from the todo list, and put the rebased commits into a single, linear branch. With --rebase-merges, the rebase will instead try to preserve the branching structure within the commits that are to be rebased, by recreating the merge commits.
You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". In fact, Git will list out every file that has a merge conflict in it with the CONFLICT flag!
@mittal: think of git rebase as copying commits from one branch onto another branch. So when you skip a commit, the original content of the commit is skipped and the patch is not applied (so all changes made to any file will not make it into your target branch).
Rebasing is not going to magically remove all merge conflicts. In fact, you may encounter conflicts while rebasing. Sometimes, you will have to repeatedly resolve the same conflict while rebasing. However, merge conflicts happen because multiple changes happen to the same chunk of code simultaneously.
If the state of your repo is
hack---F1----M1----F2 [feature] / / C1-----C2----C3 [master]
and you want to arrive at
hack---F1----M1----F2 [feature] / / C1-----C2----C3----F1'----F2' [HEAD=master]
you should use git cherry-pick
, not git rebase -i
(no need to juggle with interactive rebase, here):
git checkout master git cherry-pick <commit-ID-of-F1> <commit-ID-of-F2>
Correct me if I'm wrong, but I understand what you mean by general case as
cherry-pick, on top of
master
, all the non-merge commits betweenhack
(exclusive) and the tip offeature
(inclusive).
In the following, I'm assuming that is indeed what you mean.
As you've rightfully noted in your comment, the approach outlined above doesn't scale very gracefully as the number of commits to manually cherry-pick increases:
hack---F1---F2--- .... --- F68--M1---F67---...---F99 [feature] / / C1-------------C2---------------C3 [master]
However, you can get git rev-list
to automatically generate the list of revisions of interest, using
git rev-list --reverse --no-merges --first-parent <commit-ID-of-hack>..feature
Edit: you also need the --first-parent
flag to avoid collecting commits such as C1
and C2
, and --reverse
flag, so that commits get cherry-picked in the desired order.
You can pass the output of that command to git cherry-pick
:
git checkout master git cherry-pick `git rev-list --reverse --no-merges --first-parent <commit-ID-of-hack>..feature`
which would yield
hack---F1---F2--- .... --- F68--M1---F67---...---F99 [feature] / / C1-------------C2---------------C3---F1'---F2'---...---F99' [HEAD=master]
Looking at your original workflow, it seems like you want to ignore merges, the only problem is using -i
for an interactive rebase, which preserves merges.
git checkout -b temp git rebase --onto master hack temp * Big drawback is gone! git checkout master git merge temp git branch -d temp
Should work exactly how you want. This probably doesn't exactly solve your "general case," though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With