Reputation: 436
Often, when using git, I will make the mistake of rebasing or merging something that I didn't really want. For example, say I have three commits that I initially don't want to show in the history, and one that I do, like A-B-C-D
, where D
is the commit that I want. So I run
git rebase -i HEAD~4
and I squash A
, B
, and C
. But then, later, I decide that I actually wanted to have two commits, because A
was totally unrelated to the other three and the history would make more sense if it were on its own. What I would do now is,
git reflog | grep 'rebase -i'
which would spit out some list that ends with
<someHash> HEAD@{<num>}: rebase -i (start): checkout HEAD~4
and I would then run
git checkout HEAD@{<num>+1}
git br -D <branchIWasWorkingOn>
git checkout -b <branchIWasWorkingOn>
git rebase -i HEAD~4
and do exactly the same thing I did before, but pick
ing commit A
too this time. This is really cumbersome, and requires deleting branches, which makes me nervous that this workflow isn't particularly safe. My question is, is there a more secure way to rewrite history than this reflog
& branch deletion
method?
Upvotes: 4
Views: 105
Reputation: 18561
My favorite way to split commits if necessary is to simply git reset --soft HEAD~1
which will bring all the changes of the last commit, in your case 4 merged commits, to the staging area. From there you can recommit them as you see fit. So the basic flow would be having commits like such A-B-C-D
where D
is multiple commits you'd like to break up. run git reset --soft HEAD~1
and you'll have A-B-C
with D
's changes in the staging area. Commit as many separate times as you'd like say two, and you'd have A-B-C-E-F
.
Now thats great if the commit is at the top of your HEAD. But if you need to go back several commits, you'll still need to create a branch, git reset --hard HEAD~n
to remove extra commits (don't worry they're safe on the other branch). Then run the git reset --soft HEAD~1
. Once you've recommitted whatever you'd like, you can rebase your original branch off this branch to get to where you'd like to be.
I can't say its much cleaner than your method, might be a bit easier. For me its at least easier to visualize whats happening. That being said, if you're rewriting history, its going to be a bit messy. Just be sure you take your time and are mindful of whats getting deleted when.
Also, as a nice side note, turns out even rebasing commits out of the branch doesn't make them go away. Git caches everything. So I'd deleted a commit I shouldn't have before, but because I knew the commit hash by scrolling up in terminal, I was able to cherry-pick it back into existence. So not all is lost when you delete something.
Upvotes: 3