Reputation: 43491
Specifically, https://github.com/kodekwality/mean/commit/e6f85531279a9ce8624df180603a94837b87cd64 and https://github.com/kodekwality/mean/commit/fda7c3dc29b35e4781964e35fee6878c6827c22c appear to have the same parent, and ALMOST identical set of files and changes. Maybe I'm missing something, but they're also in the same branch. So how is it possible for the same file to be added
multiple times? Wouldn't it be modified
the second time?
Upvotes: 0
Views: 446
Reputation: 487755
In git, what you see as "a change" is always the result of comparing two commits. (Well, sometimes more than two, but mostly just two at a time.) This is the key to what's going on here.
A commit, by itself, doesn't actually "add" a file, or "remove" a file, or really, make any change to a file at all. That seems odd (git is a versioning system, isn't it?) until you realize that git is actually a file system, with a bunch of versioning support added to it. Each commit simply stores a bunch of files,1 plus the item that lets git derive changes from the previous version: the2 parent commit ID. (Plus, also, author, committer, some time stamps, and a commit message.)
So, when git says that some commit—let's call this "commit C1"—"adds a file", it does so by comparing C1 to its parent. If the parent commit lacks file a.txt
and C1 has a.txt
, then git claims that C1 "adds a.txt
".
If some other commit C2 has a.txt
, and commit C2's parent lacks a.txt
, then git clais that C2 also "adds a.txt
".
If C1's parent is the same commit as C2's parent, then obviously the single parent lacks the same file both times.
It may help to draw a part of the commit graph:
C1 - ...
/
... - o - o - P
\
C2 - ...
Both C1 and C2 are being compared to the same parent P, so if C1 "adds a.txt
", P must lack a.txt
; so if C2 has a.txt
, C2 must necessarily also add a.txt
.
This is true even if the histories later merge, so that there's just one branch containing both C1
and C2
:
C1
/ \
... - o - o - P M - o - ...
\ /
C2
(Here the merge commit M
has two parent-commits; if you examine commit M
and ask about "changes" git will either give you one diff for each parent, or what's called a "combined" diff where it looks at C1-vs-M and C2-vs-M pairwise, but then mushes together the two diffs.)
1More precisely, a commit has a "tree". The tree contains additional trees (sub-trees) and/or various files ("blobs", in git-internals-speak).
2More precisely, a commit has zero or more parent commits. Most commits have just one. Merge commits have two or more, and root commits (usually just the initial commit) have none.
Upvotes: 2
Reputation: 106389
These are indeed two distinct commits. One exists independently of the other.
makoto@LATLON-Epimetheus:~/mean$ git log --graph --decorate fda7c3d e6f8553
* commit fda7c3dc29b35e4781964e35fee6878c6827c22c
| Author: Amos Haviv <[email protected]>
| Date: Wed May 22 17:03:50 2013 +0300
|
| First Commit
|
| * commit e6f85531279a9ce8624df180603a94837b87cd64
|/ Author: Amos Haviv <[email protected]>
| Date: Wed May 22 17:03:50 2013 +0300
|
| First Commit
|
* commit 58a7ebe92d0196ef96d20f16a0376c6c44777442
Author: Amos Haviv <[email protected]>
Date: Wed May 22 17:01:43 2013 +0300
first commit
The e6f8553 commit, from the ancestor's point of view, before the fda73cd commit. The likely explanation for this scenario is due to either a cherry-pick (which can preserve the timestamp), or a patch (which does appear to have happened in the log's history:
makoto@LATLON-Epimetheus:~/mean$ git log --decorate --graph 58a7ebe..c46e52c86b34ff5d746feb883c703dd1a18e34ac
* commit c46e52c86b34ff5d746feb883c703dd1a18e34ac
|\ Merge: 6ef0d73 e99faff
| | Author: Lior Kesos <[email protected]>
| | Date: Tue Jun 18 08:13:13 2013 -0700
| |
| | Merge pull request #3 from shacharz/patch-1
| |
| | Update README.md
| |
| * commit e99fafff2c9d4ef7544f8fffa921ce8ceab26629
|/ Author: Shachar Zohar <[email protected]>
| Date: Tue Jun 18 17:25:19 2013 +0300
|
| Update README.md
|
* commit 6ef0d73d6491bd0d4c1c45a0280f81304ee2b6b5
| Author: Amos Haviv <[email protected]>
| Date: Sun Jun 9 15:35:39 2013 +0300
|
| Clearing Config File
|
* commit b0058919f7fe7cf6aa718f09a1474b4d96c7c877
| Author: Amos Haviv <[email protected]>
| Date: Sun May 26 21:18:16 2013 +0300
|
| Adding Angular-Strap + Datepicker
|
* commit 39fc1dfd68d98f2dff78434e091ee66b355dca51
| Author: Amos Haviv <[email protected]>
| Date: Wed May 22 17:17:09 2013 +0300
|
| Removing .DS_Store
|
* commit a3daa3baf6d2d5753bba96b792c6657096beea40
| Author: Amos Haviv <[email protected]>
| Date: Wed May 22 17:16:13 2013 +0300
|
| Removing DSSTORES
|
* commit 4c029d093bd8503fa31206962f98208eeef04d47
| Author: Amos Haviv <[email protected]>
| Date: Wed May 22 17:08:27 2013 +0300
|
| .DS_Store banished!
|
* commit e6f85531279a9ce8624df180603a94837b87cd64
Author: Amos Haviv <[email protected]>
Date: Wed May 22 17:03:50 2013 +0300
First Commit
Upvotes: 1