How to checkout an old commit and make it a new commit
I wanted to "follow-up" with another question about this matter: Checkout old commit and make it a new commit
But they say "Don't Do That!" so it seems I must ask a new question. (Even though it is the same question where the answer I think is best for me didn't work as expected...
If I have commits ABCDEF
(imagine these are all SHA's). I want to make the entire repository exactly as C
and then commit that to create 'G'
which is exactly like C
. So that when I am done the log is ABCDEFG even though C & G are identical.
One answer indicated cherry-pick, which seemed perfect, except it made me resolve every conflict between C
and F
. I looked at the documentation and I tried --force
anyway, and then the recommendation for --patch
. --patch
was closest but it wasn't absolute. So is there a way to make cherry-pick just choose the C
version of the conflict?
The other closest answer would be to checkout C
, but I couldn't find the magic word that would keep it on the same branch. The recent training I completed said use the "magic dash dash" at the end to tell git
you want this on the current branch, but no matter what I do it creates a "(no branch)" branch.
As I am sure you can tell, I am pretty new to git (and command line in general) but I tried to figure it out on my own. If you could use the verbose versions of what you recommend then it sticks in my head better and would be greatly appreciated. ( -a
= --all
or -a = --annotate
or -a = --albuquerque?
)
It seems so simple, and exactly what you might want to do with git -- go back a previous commit without losing the intermediary commits in case you change your mind.
Do you mind generating: ABCDEF-F'-E'-D'
where the state of the code at D'
is exactly as it was at C
(so G
== D'
)? In that case, just revert F
, E
, and D
. If you do not want the intermediate steps, revert
but do not apply, and then commit. That is:
$ git revert -n HEAD
$ git revert -n HEAD~
$ git revert -n HEAD~2
$ git commit -m 'Revert D,E,and F'
After this, the current HEAD is G, and the two commits G and C should contain the same code tree. You can verify by checking the output of git cat-file -p HEAD | grep ^tree
git cat-file -p HEAD | grep ^tree
and git cat-file -p C | grep ^tree
git cat-file -p C | grep ^tree
. Both of those commands should give the same output.
But it's not really clear why you want to keep the intermediate commits. If you want them for posterity, then do something like: git branch old-stuff
, git reset C
That will set your current branch back to C
, but D
, E
, and F
can still be viewed in the branch named old-stuff
.
I thihk you need to use git cherry-pick
.
https://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html
git cherry-pick --strategy=recursive -X ours C
git-merge(1):
The recursive strategy can take the following options:
ours
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. [...]
The "ours" and "theirs" refer to the two commits being merged. However, I'm not sure which way around git cherry-pick
treats the commits, so you might need -X theirs
instead. You could make a new branch, to try it and see.
上一篇: GIT如何在没有提交的情况下重置
下一篇: 如何检出旧的提交并将其提交给新的提交