Hongxu Chen
Hongxu Chen

Reputation: 5360

How can I strip several old commits but keep all the other commits unchanged in a git?

Suppose the structure of the commits is like the one below:

                 B'---C'           X'
                /      \          / \
           A---B---C---D---...---X---Y---Z(master)

And now I need to strip all the commits between A and X,

                         X'
                        / \
                   A---X---Y---Z

AFAIK, there are at least 2 way to achieve this:

But there are always some conflicts that I need to manually handle.

Since I only would like to purge all the commits after A and before X and I don't need to change any git tracking results after each commit(for instance, the newly generated commits X share the same contents as the old X commit), is there an easier way to do so?

Upvotes: 4

Views: 433

Answers (3)

Ajedi32
Ajedi32

Reputation: 48428

Note: This solution will squash the commits you want to "strip" into X, so that the new X commit and all following commits have their files in the exact same state that they are now. If this isn't what you wanted, see my other answer.


git checkout -b temp A
git merge X --squash
git commit -C X # Create new x commit
git checkout master
git rebase --preserve-merges --onto temp X # Rebase onto new X commit (should produce no conflicts)
git -d temp

Upvotes: 1

Ajedi32
Ajedi32

Reputation: 48428

Edit: This solution will remove the old commits (including any changes made in them) from the repository. This aparently isn't what the op was asking but I'll leave the answer here anyway for future readers.


git checkout master
git rebase --onto A X~

I can't guarantee there won't be conflicts, but if you do run into any you can resolve them manually, git add the files with the conflicts, and then type git rebase --continue.

Alternately, you could force git rebase to automatically resolve any conflicts by applying the more recent changes over the top of any conflicting changes made in A (or before):

git checkout master
git branch backup # Just to be safe
git rebase -s theirs --onto A X~
git branch -D backup # When you're sure master has everything you need

Upvotes: 0

che
che

Reputation: 12273

I'd try something like:

git checkout -b new_X X
git rebase -i A # set everything to 'squash'
git checkout master
git rebase --preserve-merges --onto new_X X

This hopefully should keep commit changes the same, so there would be conflicts. If this fails, I would probably resort to low-level commands like git commit-tree and some script to create the new structure from original trees.

Upvotes: 0

Related Questions