Reputation: 162995
Is there a way in git which shows the list of files being changed in a whole branch?
I find the post about showing how to list all the files in a commit:
How to list all the files in a commit?
Is there a way to do that for all the commits in a branch? And how can list all the commits in a branch?
Thank you.
Upvotes: 0
Views: 87
Reputation: 488183
As Mitchel Paulin noted, commits hold snapshots, not changes. You must pick two snapshots and ask Git to compare them, before you can find any differences. Consider this the equivalent of a spot the difference puzzle: each commit snapshot is a full picture of your source, and you have to put up two pictures before you can see what's different.
The question to which you linked, How to list all the files in a commit?, has a lot of answers, but none of them note the fact that each commit actually holds two things: a snapshot plus some metadata. That is:
Each commit is numbered. The numbers are big ugly hash IDs—they look like random strings of letters and digits—but these are actually numbers. Every commit gets its own unique number. (They're actually cryptographic checksums.)
Each commit stores a full snapshot of every file—not changes, a snapshot. The files in each commit are frozen for all time, and to save space, are de-duplicated across all commits (since many commits share most of their files with many other commits), but each one has a full copy.
Each commit stores some metadata such as the name and email address of the person who made the commit. One of those metadata items, though, is the commit number of the previous commit. Git calls this the parent of the commit.
These parent links mean that Git actually works backwards. That is, a branch is just a chain of commits that ends with some particular commit:
... <-F <-G <-H
Here H
stands in for the big ugly hash ID of the last commit in the chain. Inside commit H
, Git has stored the hash ID of earlier commit G
. We say that G
is H
's parent, or that H
points to G
.
When you have Git show you what changed in some commit like commit H
, Git is really extracting both G
's snapshot and H
's snapshot, and then comparing them. Whatever is different, that's what changed. If you just want the names of the changed files, that's particularly easy for Git, because of the de-duplication trick it uses.
But this also leads to the answer to the other part of your question:
Is there a way to do that for all the commits in a branch? And how can list all the commits in a branch?
If H
is the last commit in a chain of commits, and H
points to G
, then G
is the next commit backwards. Git can thus use H
to find G
.
Commit G
, meanwhile, holds the big ugly hash ID of its parent F
, so Git can use G
to find F
. That lets Git step back one more step.
F
also holds the hash ID of its parent, so from F
, Git can step back to the next—well, previous—commit.
This is just what git log
does: it starts at the end, and works backwards. Almost all of Git does this same thing, working backwards.
A branch name like master
or branch1
just holds the hash ID of that last commit. When you add a new commit to a branch, Git stores the new commit's hash ID into the branch name right then and there, and now the new commit is the last commit.
There's another tricky bit though:
I--J <-- branch1
/
...--F--G--H
\
K--L <-- branch2
Which of the two branches are commits up through H
on?
Git's answer is: they're on both branches. In fact, in a real repository, most commits are on most branches. Running git log
from branch2
, say, will start at L
, move back to K
, move back to H
, move back to G
, and so on, all the way back to the very beginning of time in the repository.
When someone asks about all the commits on some branch, they almost always don't really mean what they're asking. They almost always mean on some branch, backwards, until some point where I think Git should stop early. Git makes you tell it, explicitly, where to stop. That's what the git log branch1..branch2
syntax is about: it says commits you find by working backwards from branch2
, but excluding commits you find by working backwards from branch1
. Here, that would be commits K
and L
only, starting with L
and going back to K
. The next commit back—H
—is on branch2
, but it's also on branch1
, and we told Git to leave out all branch1
commits, so that leaves out H
, and G
, and everything before them.
Upvotes: 2
Reputation: 3418
Changes only make sense when relative to something else. For example, you could do a diff against some branch (say master) with the following git log branch1..branch2
.
Or maybe git diff --name-status branch1..branch2
Upvotes: 0