Home > Software engineering >  Git checkout to specified commit doesn't ignore previous commit?
Git checkout to specified commit doesn't ignore previous commit?

Time:11-17

When I do git checkout 10bec0c with the intention of wanting to ONLY the last changes (3) but why 1 and 2 is included? I use cherry-pick it's also the same. How to get only a specified ONE commit?

enter image description here

CodePudding user response:

Please, try creating a branch for the commit by git checkout 10bec0c temp_branch then inspect logs by git log --oneline --graph --decorate.

CodePudding user response:

This depends on what you mean by "get" (as in get a specified commit).

The key here is that each Git commit holds a full and complete snapshot of every file, as of the form that file had at the time you (or whoever) made the commit.1 In other words, commits do not store changes.

Using git checkout or git switch --detach to check out a particular commit simply extracts that commit, so that the files you have in your working tree, where you get to see and work on / with your files, are the files that are stored in that snapshot, as they existed on that day and time.

You can, however, view a commit as changes. This works because every commit remembers the raw hash ID of its immediate predecessor commit (or commits, for a merge commit). Depending on which way your viewer ordered the three commits it displayed here:

<image> 1     ff5cbab
<image> 2  ✅ 26b5656
<image> 3  ✅ 10bec0c

the predecessor (or parent) of 26b5656 is either ff5cbab or 10bec0c. I'll assume it's ff5cbab here, i.e., the commits go:

... <-ff5cbab     <-26b5656     <-10bec0c [latest]

and that your viewer shows them "upside down" as compared to, say, git log --graph, which would show the latest first, instead of last.

If this is the case, the command git show 26b5656 causes Git to:

  • find commit 26b5656;
  • inspect the backwards-pointing arrow coming out of it to find the previous (or parent) commit ff5cbab;
  • use those two hash IDs to extract both commits to a temporary (memory) area; and then
  • compare those two commits' snapshots.

For each file that is the same in each commit, this comparison says nothing at all. For each file that is different, Git computes some way to convert the older file to the newer one. This is a diff, i.e., a recipe for changing one file into another. Git then shows you the file's name and the recipe.

You can get a diff between any pair of commits using git diff, by giving it both commit hash IDs. If you pick the parent-and-child pair and use the hash IDs in the order:

git diff <parent> <child>

you get a recipe for turning the parent commit into the child commit. If you reverse these:

git diff <child> <parent>

you get a recipe for turning the child into the parent—i.e., a recipe by which you can "undo" the commit.


1These snapshots are stored in a special Git-only format, in which files are compressed—sometimes highly compressed—and de-duplicated. So if you have a million commits, each of which contains a 10 megabyte file, but the 10 megabyte file is identical in all million commits, those one million 10 MB files consume ... 10 MB, or even less if the compression is good. It doesn't take the implied 10 terabytes, because it's been de-duplicated 999999 times.

  •  Tags:  
  • git
  • Related