Greg McGuffey
Greg McGuffey

Reputation: 3316

Why would a commit in git updated files but not shown those files?

We had a situation where a developer did a commit, changing two files (shown in the commit), but in fact many more files were changed. I.e. we can look at a file in the previous commit, see some content, then look at the same file in the offending commit and that file is different (missing content), but the file does not show up as changed in offending commit. How is this possible?

We presume that the developer of the offending commit didn't pull before pushing and pushed an older version up, but I'd expect to see all the files that were changed accidentally as well as the desired changes. Since I'm not seeing those changes, I'm wondering if something else happened.

Here is what we are seeing (for just one file with change but not in commit)

Update

I'm looking at commit history in GitHub. Click on commit and it shows files changed. In offending commit, there are two files listed. However, again in GitHub, if you compare a problem file between the offending commit and the previous commit (browse files button when looking at commit), a file not listed in the offending commit is changed.

I checked the parents (in GitHub) and it indicated the the two commits I'd expect as parents are the parents. However, I also began to suspect that if I followed the parents down far enough, we get to the problem. I ended up using SourceTree to look at the branches...wow....looked like the LA free system after an earth quake.

The apparent cause is that the offending commit was based on a very old commit in the develop branch, as suggested by Mark Adelsberger. I don't have confirmation, but pretty sure the committer googled enough to use the -f switch.

I also found a later commit that did show the changes to the files. I'm pretty sure another dev then did a merge from the now fubared branch, which then updated all those files in their commit. They apparently didn't look at the files they were committing, noticing that instead of like 3 files changed, there where 60+. Things are being straightened out now.

Upvotes: 0

Views: 312

Answers (1)

Mark Adelsberger
Mark Adelsberger

Reputation: 45659

Since you aren't specifying the exact commands and output that are leading to your conclusions, it's impossible to draw many definitive conclusions. However, I can guarantee two things:

1) A normal attempt to push without pulling will not erase changes that had already been pushed; it will generate an error. In distributed development this happens all the time, so if it caused changes to be erased then git would not be a viable version control system in the first place. (An incorrect procedure for dealing with that error could look roughly like what you're seeing, though; I'll come back to that.)

2) There is no procedure whereby commit A differs from its parent commit P in a way that is not shown as a change in A's patch. This is because commits are always stored as snapshots of the project, and changes ("patches") are calculated by examining the commit and its parent, so at an almost mathematical level it makes no sense to claim such a situation.

So assuming everything you've said is accurate, and varying only things you've implied/apparently assumed, the most reasonable explanation is that y is not the parent commit of x.

One way that could happen is if the developer who made x was on a separate branch (perhaps one that was created before A):

o -- A -- o ... o -- y <--(master)
 \
  x <--(branch)

In that case you could simply merge branch into master.

It's possible to accidentally get into a state very much like that, if the developer was still on master (hadn't branched), but tried to push without pulling, and when presented with an error responded with

git push -f

This would perform a "force push", which can remove commits from a branch's history. It should not be a part of anyone's routine workflow and often is forbidden by configuration of the server. The result would be on the server

o -- A -- o ... o -- y 
 \
  x <--(master)

and other devs trying to pull master should get errors because master has moved in an unexpected way.

In that case, I'd have the developer who created x do the following to clean it up:

First, create a new branch at x and push it. Then

git checkout master
git reset --hard *&lt;ID-of-commit-y&gt;*
git push -f

Where <ID-of-commit-y> is either the commit ID of, or some other expression that resolves to, commit y. (If you're examining commit y, then you must have such an expression you're using to find it.)

Then you'll be back to

o -- A -- o ... o -- y <--(master)
 \
  x <--(branch)

and could merge branch into master (or rebase branch onto master and then fast-forward master, if you prefer).

Upvotes: 1

Related Questions