Chris Torek <chris.torek@xxxxxxxxx> writes: > On Mon, Dec 2, 2024 at 4:15 AM tao lv <thebookofunknowable@xxxxxxxxx> wrote: >> I want to revert the code to a specific commit. ... > > OK, first some background: > > * A commit _is_ a full snapshot of every file, as of the state > it had at the time you (or whoever) made that particular > commit. Hence, if you want the particular files from a > particular commit, you simply check out that (historical) > commit. > > Now: > >> I don't want to revert each individual commit; I just want to restore >> the code to this specific commit while retaining all the current >> history commits. >> >> How can I achieve this? Is there a better way than using the revert function? > > git checkout [--detach] <hash> # or git switch --detach <hash> > git reset --soft <branch-name> > > git restore --no-overlay -S -W <hash> While that would _work_ in the sense that you can revert the effect of what the discarded commits did, I would not recommend any of the above since it does not leave any record of what you discarded. Imagine that I regret doing everything since we tagged, say, v2.47.0 release and want to discard everythig on 'master' newer than that commit. If I want to "keep" the history of failed commits that I regret having made since v2.47.0, here is a way to do it: $ git checkout master $ git reset --hard v2.47.0 $ git merge -s ours --no-ff -m 'Discard everything since v2.47.0' master@{1} The first two steps just discard the unwanted commits. The third step is a trick to - Keep the tree contents of the current commit (i.e. -s ours) as the result, - Make sure the result is recorded as a merge commit (i.e. --no-ff), not "fast-forward" to the tip of the history I am discarding, and - Record the discarded history (i.e. master@{1}) as the side branch of the resulting history. The last part would help if I later need to merge changes that were based on 'master' I am discarding. The presense of the side branch makes sure that only the effects from the new work done on the discarded history, and not from the commits such a new work was based on (which are the commits I regret having made and I am discarding), are taken into account when computing further merges.