Commit appears in the history, changes are not in the file and are not displayed in a separate file commit history

I had a really strange problem with git. Yesterday I pushed the fix, and after that several people pressed. Now I can see my commit in the history on github, but the changes I made are not in the revision of the HEAD file, and if I look at the history of a single file, my commit does not appear. My teammates tell me that everything they did was a regular push and push. There were no conflicts with the file I changed. If someone used force, I would expect my fixation to completely disappear. If someone messed up the resolution of the merge conflict, I would expect the merge commit to cancel my changes and be reflected in the commit history for the file. But somehow this is not so. To simplify:

  • I am modifying a .txt file and doing commit ABCD
  • I press abcd to github
  • Other people push other commits without affecting the .txt file
  • If I look at the repository committing transactions on github, I see my commit and I can pull the diff change
  • If I look at the latest version of file.txt on github, my changes are not there.
  • If I look at the commit history of file.txt, ABCD does not appear, the last commit in this file is the commit before ABCD.

How does this happen?

Edit: for discussion in the comments, here is a snippet of my commit schedule

  * |  8c1d372 ...
 * |  98dbad7 Merge branch 'master'
 | \ \  
 |  * |  8d64a09 ...
 |  * |  12beb68 ...
 |  * |  1c94b6d Merge branch 'master'
 |  | \ \  
 |  |  * |  80b6285 ...
 |  |  * |  9781fad ...
 |  |  * |  f12fc90 ...
 |  |  * |  61411fa ...
 |  |  * |  291333b ...
 |  * |  |  aeee93f ...
 |  | / /  
 |  * |  bcfbf65 Merge branch 'master'

My fix that disappeared is 9781fad. If I checked 8c1d372, my changes will disappear. However, no commits after my action affect the file that I changed.

+10
source share
3 answers

The actual answer (not a super-long comment).

Here again a bit of the graph plus my own annotations:

* | 8c1d372 ... <-- lacks desired changes * | 98dbad7 Merge branch 'master' <-- ? (interesting #1) |\ \ | * | 8d64a09 ... | * | 12beb68 ... | * | 1c94b6d Merge branch 'master' <-- ? (interesting #2) | |\ \ | | * | 80b6285 ... <-- probably also has desired changes | | * | 9781fad ... <-- is commit that makes desired changes | | * | f12fc90 ... | | * | 61411fa ... | | * | 291333b ... | * | | aeee93f ... | |/ / | * | bcfbf65 Merge branch 'master' 

Since none of them explicitly canceled your changes, and they should be in a file that no one should have edited, he is almost sure that the one who lost your changes did this by making a bad merge.

Two mergers that I noted are interesting. # 1, commit 98dbad7 , has two parents: one of them we cannot see (from the bottom of the graph) and one, we can, 8d64a09 . A git log from this point will show both stories. git show 98dbad7:path/to/file will show the version of the file attached to the merge commit (i.e., regardless of who did the merge, the correct version of this file was). If this is the wrong version - if the required changes are not in this file, then either the merge itself went badly or had bad inputs. Presumably, a parent that does not matter should not have a change, so at this point we should follow another parent, i.e. 8d64a09 .

You can git show 8d64a09:path/to/file to check if this version has changes or not. If your changes are there, then this is 98dbad7 message that 98dbad7 them. If your changes are not, we must click.

For completeness, we can look at 12beb68 , but this is probably not a criminal. This is the usual single parent 1c94b6d , 1c94b6d .

Commit 1c94b6d is our second interesting merge. As with any merger, it has two (or more, but usually two) parents. This time we can see both, and they commit 80b6285 and aeee93f .

Commit 80b6285 probably has your changes since it is a regular commit whose 9781fad is commit with your changes. And commit aeee93f will not have your changes because it is from the merge side, which, well, does not have your changes. :-) You can git show 80b6285:path/to/file just to make sure that the one who made this commit doesn't secretly (unlike frankly) returned them, and then git show 1c94b6d:path/to/file to notice that this interesting-merge- # 2 discarded your changes.

The chances are very high that one of these mergers lowered your changes. Why else an interesting question, but the person who made this merger should answer it. They did something β€” perhaps a check, perhaps the flag set for the merge β€” that discarded your changes during the merge. Find out which merger has thrown the change, and talk to the person who did it to find out what they did, what threw them.

Getting changes back

It’s very easy to revert your changes: just use git cherry-pick , which runs diff for you, and then applies that diff to the current commit. So, you will return to master and just git cherry-pick 9781fad . This will be diff 9781fad^ ( 9781fad parent, which is f12fc90 ) versus 9781fad -a diff showing your changes, and apply them to the current commit and commit again, reusing the original message. (If your commit affects several files and should only return changes to one file, this requires a little more work, but assuming that it is one file, this is an easy fix. You still need to make sure that no one has canceled it in a future merge , although.)

+10
source

This answer consists of instructions on how to find the answer.

Use the commit graph viewer (or just git log --graph , often best called as git log --graph --oneline --decorate --all ) to see where your particular commit is in terms of Git DAG. If the graph is good and linear, it will be easy to follow. If it is full of branching and merging operations, it will be harder, and probably someone did a bad merge that introduced the problem. If it is filled with unrelated branches, or even has only one unrelated branch, perhaps this is a problem.

(Using --all , you will see all labels, including all branch names, and with --decorate will be attached to the commits they point to. The --oneline parameter simply compresses the log output on a single line per commit, inserting much more into the text box.)

Use git show to view any regular (non-merge) commit: this shows you the commit metadata (author, time, log message) and runs git diff to compare the tree for this commit with the tree for that commit parent. For example, git show ABCD should show your change, since the tree you made changed the file compared to the tree you started from before you committed ABCD .

Assuming your ABCD commit is where you want it to be inside the chart, look at subsequent commits (using git show again) - subsequent commits are those closer to HEAD - to see who changed your change. Then you can try to figure out how they did it, perhaps by talking to them.

If the subsequent commit is a merge - commit with two or more parents - git show usually doesn't show you much, and you need to either use git show -m or run git diff manually to see two comparisons: from the first parent to this commit and from second parent to this commit. The -m flag tells git show to make two different differences for you. (You can provide -m for non-merge commits, it just does nothing for them. This is not the default, because merge usually shows a lot of redundant changes.)

(By the way, git log -- path does not actually show the history of files, because Git has no history in each file. Instead, this git log starts by finding all the achievements, going through the commit graph, starting with HEAD , but then issuing commits, which do not seem to affect the file.It’s not clear why you don’t see ABCD commit here, but the version of the log graph and the output of git show should make this clearer.)


In the comments below: When describing the output of git log when checking commits marked 4 and 5 (when checking 5 we see 5, 4, 3, 2 and 1, but when checking 3 we see only 3 and 2), at least one of 4 or 5 should be a merger.

Assuming 4 is a (single) merge union, we can draw this particular piece of the graph as:

 ... <- 1 <------- 4 <- 5 <-- master / ... <- 2 <- 3 <-- 

Here, the ( master ) branch points to commit 5 , which is a regular commit without merging, while commit 5 points to commit 4 : 4 is the parent of 5 . Commit 4 - merge merge, merge the contents of commits 1 and 3 ; he has two parents, 3 and 1 (in some order). Commit 3 is not a merge with 2 as a parent. We know almost nothing about commits 1 and 2 : I drew them as if they have different parents, but maybe they have the same parent.

It is possible that commit 5 is a merge, or that 4 and 5 are both mergers; all you can say with confidence, based on 1 that appears when git log run from 5 , but not when git log run from 3 , is that 1 not in the history for 3 .

Please note that the story is found by following the arrows in the direction in which they are indicated, and never goes against the arrows. If we start with 5 and 4 is a merger, it has two outgoing arrows, so we go through both stories to get story 4 .

While git log --graph draws the story vertically (and does not put it in the arrows), it shows the same information that you cannot see without --graph , but which is vital for future operations, such as merges, which depend on the chart so far .

Note that if the above snippet of the graph is accurate (I still guess since you did not send git log --graph --oneline --decorate --all output snippets), then we can almost certainly tell what happened with your changes in commit 1 : who did the merge in 4 , told Git to destroy your changes, taking what was in commit 3 .

+3
source

All Articles