How can I remove all commits except the last x from a branch?
Asked Answered
L

1

6

I need to find a way to remove all commits except the last (most recent) 159 from a branch using Git. I'm also fine with creating a new branch and moving the last 159 into it, if that seems like a better way to do it for you.

Any ideas? I've already tried this but it only seems to allow me to revert back to a certain commit (and that's not what I want).

Lienlienhard answered 18/4, 2016 at 8:53 Comment(7)
Does cherry-picking solve your problem?Make a new branch and cherry-pick the commits you want.Impenitent
What should be the 160th commit back on the new version of the branch? Should the 159th have no parent and introduce that state of the whole source tree? Or do you want to have one parent of the 159th commit that introduces the state before that commit as one commit?Folger
@BjörnKautler's question is one key to getting the correct result. The other is that, whatever the answer to that is, you must decide what initial state the associated source tree should have. Whether or not you make the new branch as an orphan (new root) branch, you must pick a source tree for the first new commit on the new branch. This will affect what happens with the other 159 commits.Triform
I'd like the new branch to begin with the 159th commit (so no, it shouldn't have a parent).Lienlienhard
In that case, you can git checkout --orphan newbranch branchname~158, commit, and then git cherry-pick in the entire range of branchname~158..branchname to get the 158 remaining commits copied. This assumes there are no internal branch-and-merge operations in that range; if there are, you will have to work harder, count carefully, and/or use git filter-branch or a script doing a lot of git commit-trees to copy them.Triform
@Triform Ahhh, that's the problem! I have a lot of merge commits in there and it keeps failing because of that. To me, git filter-branch seems to be the easiest way to get the job done. What's your suggestion to make it work?Lienlienhard
The trick with filter-branch is that (like rebase) it copies commits. Unlike rebase, it copies them by keeping the original source tree intact by default, and simply mapping parent IDs. If you're comfortable with graph theory, basically it makes a new subgraph by copying the nodes of the specified subgraph (from the X..Y notation) and then pastes the branch label on the tip-most copied commit. Each commit (and if you set an index or tree filter, the index or tree) is passed through the various filters before doing a new git commit-tree with -p arguments from the map.Triform
D
9

The most simple way is to create an orphan branch and then to cherry-pick range of commits to the new branch.

# create orphan branch 
git checkout --orphan <branch>

git cherry-pick <SHA-1>...<SHA-1>

git checkout --orphan

Create a new orphan branch, named , started from and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.


How to add the desired commit into different branch.

git cherry-pick <SHA-1>...<SHA-1>

Apply the change introduced by the commit at the tip of the master branch and create a new commit(s) with this change.

The syntax of the ... is a commit range. grab all commits from start (exclude) to the last one.

enter image description here


Read out the full git cherry-pick documentation for all the options you can use

Distillation answered 18/4, 2016 at 9:7 Comment(4)
Thank you! But let's say "one" is my most recent commit, how can I make sure that it gets included when cherry-picking? Because according to your answer, "one" and "three" will be excluded and only the commits between them will be copied (but I'd like to include "one").Lienlienhard
You can choose which to commit to start from and supply a range. for example: git cherry-pick 159...1 if you want 160 use: git cherry-pick 160...1Distillation
you can also use a single commit hash using git cherry-pick commit-hash without specifying range.Alloy
But he asked for multiple commits. That's the original questionDistillation

© 2022 - 2024 — McMap. All rights reserved.