List of crushed commits

After doing an interactive reboot: git rebase -i HEAD~20 I get a new commit, for example. ea1234ea

I know the story is in reflog, but how can I get a list of commits crushed in this commit, including their identifiers (sha)?

git show ea1234ea will display a commit message that lists messages that are compressed but without identifiers.

+4
source share
1 answer

Start with git reflog . The result will look something like this (but with a lot of rebase -i entries):

 aa4e140 HEAD@ {0}: rebase -i (finish): returning to refs/heads/branch aa4e140 HEAD@ {1}: rebase -i (squash): c1-c3, squashed 3a422a7 HEAD@ {2}: rebase -i (squash): # This is a combination of 2 commits. f7cac12 HEAD@ {3}: rebase -i (start): checkout HEAD~3 283263c HEAD@ {4}: commit: blah yadda etc, but not a rebase 

This last rebase line has a SHA1 commit, which was HEAD before you did rebase -i . You might want to stick a temporary branch or label on it, although this is not technically required. Here I put on it a lightweight tag called temp :

 git tag temp 283263c 

Now you can simply run git log temp or (to limit it to only those that you recreated):

 git log temp --not HEAD 

or

 git log temp ^HEAD 

(these are two ways to write the same thing) 1 or:

 git log -n 20 temp 

(this uses the fact that there are 20 commits in rebased HEAD~20..HEAD , which is only true if the original story was linear and, of course, depends on this part ~20 ).

When you are done with the timestamp, delete it:

 git tag -d temp 

The way this works is that rebase -i doesn't actually remove any , it only adds a new one . (This is actually true for almost every git command. An exception is the garbage collection process, which deletes objects without references.)

The full set of commit-and-branch arguments for rebase (that is, ignoring important flags such as -i and -p ): start-point, destination, and branch-name. The documentation will slyly mask :-) the first two of them are “upstream” and “on” (seriously, “on” is not a bad name, and I will stick to it below, but the “upstream” is misleading in some cases ) All commits after the starting point, right up to the tip of the branch, are copied (or omitted or crushed or something else), essentially picking them up in cherry, one at a time, as a new commit is added to the branch grown for the purpose. If the original commit tree looks (partially) as follows:

 old -- start-point -- c2 -- c3 -- c4 <-- branch \ onto -- c6 -- c7 <-- another-branch 

then rebase starts by copying (or “playing back changes from”) c2 (the first commit after the start point) to an identical change (but with different commit information), c2' , placing it so that onto is its parent:

 old -- start-point -- c2 -- c3 -- c4 <-- branch \ onto -- c6 -- c7 <-- another-branch \ c2' 

Then it copies c3 to the new ( c3' ) version with c3' parent c2' , etc. When everything is done, it will undo the branch label from c4 and insert it, indicating the last new commit ( c4' ) instead:

 old -- start-point -- c2 -- c3 -- c4 <-- [no label] \ onto -- c6 -- c7 <-- another-branch \ c2' -- c3' -- c4' <-- branch 

Note that the old commits ( start-point , c2 , c3 and c4 ) are still there, they no longer have a branch mark. Also note that in this particular case (using the --onto argument, as shown with this particular commit tree), a commit named start-point itself becomes "invisible" (in the same sense as c2 through c4 ) like this as it no longer has a branch label or a label pointing to it - unless, of course, you set it before or after you rebase. (Usually there are no such “missed” commits. Of course, in the interactive permutation you can skip it, but then it's clear enough for you to do this.)

Unmarked ("invisible" or "hidden") are blocked until they remain in the reflog (90 days, unless you change the default setting). To make them stick even longer, set a label - for example, a branch or tag name - to point to them. This is what I am doing with the temp tag above. Now they are visible again, and they can be easily seen in any commit-tree handler file, such as gitk or git log .

(If you ask the interactive rebase to “squash” several commits, it simply puts the changes together into one fixed one. Since each new commit is a copy - “replay”, it’s as if simple: just save putting more changes together, fixing them as one compressed-commit .If you omit the commit, it just skips it, copying only the remaining ones. If you re-order commits, it just copies them in the new order.)


1 There are many ways to write this down. In fact, git log HEAD..temp does the trick, even if it doesn't look right, somehow. :-) In these versions, everyone assumes that HEAD is still the name of the branch on which rebase was enabled. If you were in the squiggle branch, you can use git log temp ^squiggle as soon as HEAD moved elsewhere, for example.

+2
source

Source: https://habr.com/ru/post/1502735/


All Articles