Can a file be both staged and unstaged in Git?
Asked Answered
T

4

19

While working on another file, I edited README.md and then ran git add README.md. When doing a git commit, I see that README.md is both in the "Changes to be committed" and "Changes not staged for commit".

Does this make sense? Where in .git could I look to see the authoritative state of this file?

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   README.md
#       modified:   utils/arrterm
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   README.md
Thus answered 19/7, 2014 at 7:21 Comment(1)
You can think of this like this: you change 10 lines. With git add -p you add only the first 5 changes. Now your file is also staged and not staged.Still
A
21

This means part of the changes you made are staged for commit and parts are not.

You can check what is staged if you run

git diff --staged -- README.md

and check for what is unstaged by running

git diff -- README.md

Most version control systems generally only store the changes between two states. The way git works, while you make multiple changes to a file, you will have to add/mark each of them to be part of one set of changes a.k.a a commit. When you use git add this is done automatically.

However it is not the only way you add can all your individual changes(hunks) to your "index". You can for example make multiple changes to the same file and commit them in different commits or add only specific changes to a commit. E.g. to explicitly add some changes to your "index" but not others, you can do so by using git add -p to add only some "hunks" (groups) of the changes instead of the whole list of changes itself.

What has happened here is that the changes you made to README.md before staging ( git add) will show in staged and any changes you made after staging README.md will show as unstaged as you have got above.

Alarm answered 19/7, 2014 at 7:23 Comment(8)
It's important to know that git stages and commits content lines, not files. This can be very handy, eg to commit some of the changes in a file while leaving the others for a future commit. Also, a git gui will make it easier to see and change which parts of the file are staged.Hesitate
@Jerry101: "content lines, not files" --- I'd say "changes". Because: deleting a file doesn't contain lines. The same for changing permissionsMangrove
@Mangrove yes, but if you change which parts of the file are staged/unstaged, it does that in "hunks" which seem to be one or more lines for text files. Do correct me if I'm wrong.Hesitate
@Jerry101: that's right. You choose diffs, hence changes. That's my exact points.Mangrove
staged is an option, so the correct syntax is --staged. (It's a synonym for --cached, BTW, and I generally see --cached used more, but --staged does work too.) README.md is not an option, so the correct syntax is -- README.md.Automotive
my apologies, spacing typos :(, fixed nowAlarm
But if I make changes to a staged file, then run git status, shouldn't it say that the staged file is modified ? I don't understand how this is possible. I am new to git BTW.Joplin
Git does not stage files it stages only changes. Some changes in a file can be staged and some not even while adding first time as hunks (-p) , the time of modification is not relevant, what matters is only whether a change(hunk)[1] is staged [1] gnu.org/software/diffutils/manual/html_node/Hunks.htmlAlarm
G
8

Where in .git could I look to see the authoritative state of this file?

Use git diff:

  • git diff -- yourFile will give you the changes not yet staged (not yet added to the index)
  • git diff --cached -- yourFile will give you the changes already added to the index.

See more at "Changes, not files":

Most version control systems work with files. You add the file to source control and the system tracks changes from that moment on.

Git concentrates on the changes to a file, not the file itself.
A git add file command does not tell git to add the file to the repository, but to note the current state of the file for it to be committed later.

See also "git add -p: The most powerful git feature you're not using yet"


Note that git status -v -v will soon (Git 2.3.4, Q2 2015) shows you both diffs (staged and unstaged), possible listing different diffs for the same file.

See "Show both staged & working tree in git diff?".

Gallopade answered 19/7, 2014 at 7:25 Comment(2)
Thanks, I understand the changes idea. I'm more interested in understanding why README.md was showing up twice in the status.Thus
@MarkHarrison because you added a change before, then made a new oneGallopade
A
3

Actually the state you see is very easily to reproduce:

git init
touch test
git add test     #1
echo 42 > test   #2
git status       #3

in #1 we stage the empty test file. #2 changes the contents of the file. These changes will no be staged (since you need to explicitly stage changes using git add). The output of git status in #3 tells you exactly that.

To see which changes have been staged, run git diff --cached. To see which changes to your working copy files have not been staged, run git diff.

In your question you state that you ran git commit. From your git status output it seems as if the commit was not created, probably because you did not enter a commit message. Check the output of git commit, git probably told you what went wrong when trying to create the commit!

Arturoartus answered 19/7, 2014 at 7:30 Comment(0)
G
3

Answer to "Does this make sense?"

It only makes sense if you understand that git does not store differences it stores snapshots.

In the example you describe there are two versions of README.md in your changes. The staged one is the version that you're currently happy with and will end up being the latest snapshot of the file if you choose to commit it. The unstaged version is is a potential snapshot that will replace the currently staged version if you choose to stage it.

Read the section 'Snapshots, Not Differences' in the following link for more understanding on how git works:

http://git-scm.com/book/en/Getting-Started-Git-Basics

Also look at the following link for a further explanation of the scenario that you've included in your question (in particular the section 'Staging Modified Files'):

http://git-scm.com/book/en/Git-Basics-Recording-Changes-to-the-Repository

Gwenora answered 19/7, 2014 at 7:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.