[note: comments turned into answer - the top section is all you need, the rest is just explication]
The only change the patch hunk makes is to add that one line. If you take out the added line, the patch becomes a directive to change the file by making no change to the file, which is not very sensible. The error message here is kind of silly, but the action you need is simply "skip this one".
Lots of details, read only if interesting
Note that there are, at all times while you're working on your next commit to make, three of what I call active copies of each file. Well, more precisely, there are up to three such copies. The first one is whatever you committed previously, or had inside the commit that you got when you ran git checkout
. This copy, being stored inside a commit, is fundamentally read-only: you cannot change it, as it's part of that particular commit. But you can access it whenever you like. For instance, given a README.txt
file you can run:
git show HEAD:README.txt
to view it. Internally, this file is stored in a special Git-only format (zlib-deflated and perhaps even further compressed)—non-Git programs in general cannot read this copy of the file.
There's also a copy of that same file in your work-tree, where you can work on it. This copy is stored in its ordinary computer format, so that you can read it. Your editor—atom or emacs or sublime or vim or whatever it is you use—can read and write the file. Your compiler, if you compile programs, can read and write it, and so on. You need not do anything special with the file, as it's just like any other file. Oddly, Git almost doesn't care about this copy of README.txt
—Git has to be kind of hands-off, since anything can change it!
But there's a third copy of README.txt
too, and that's the one that is in what Git calls, variously, the index, or the staging area, or the cache. (Which name Git uses depends on which Git documentation you're looking at.) This third copy, which you can see with git show :README.txt
, is in the special Git-only format, but unlike the copy in a commit, you can overwrite this one. The usual way that you overwrite this one is with git add
, which simply copies the work-tree file into the index.
Hence, the index :README.txt
starts out matching the HEAD:README.txt
file. If you change the work-tree copy, the HEAD and index versions still match. If you then git add README.txt
, that overwrites the index copy from the work-tree copy, and now HEAD:README.txt
and README.txt
no longer match, but :README.txt
does match README.txt
.
This is where git add -p
comes in: if the index copy and the work-tree copy of some file are different, you can have Git come up with a patch—a set of hunks, each of which says to add and/or remove some line or lines—that, if applied, would change the index version to match the work-tree version. If Git were to follow all the instructions in the patch, that would change the index copy of the file to match the work-tree copy, just like git add
would do.
But now Git has you go through that patch, one patch-hunk at a time, and:
- tell Git to apply it as is; or
- tell Git to skip it entirely; or even
- fiddle with the change instructions so as to partially apply the patch.
When you choose to apply a particular patch-hunk (perhaps after editing it), Git extracts the index version of the file, applies that set of instructions, and goes on to look at the next one. If you skip it, Git just goes on to the next one.
Note that there is a companion to git add -p
: running git reset -p README.txt
tells Git that it should compare HEAD:README.txt
and :README.txt
(HEAD and index versions), and prepare a patch that would, if followed to the letter, change the index copy so that it matches the HEAD
copy again. Then Git goes through the same process as for git add -p
.
Last, let's take a quick look at git status
. This does a lot of useful things, but the one where it tells you about changes staged for commit and changes not staged for commit consists of running, in essence, two git diff
commands. The first one is:
- What's different in
HEAD
vs the index?
For every file that is exactly the same here, Git is just silent about that. But if HEAD:README.txt
and :README.txt
are different, Git tells you that there is something staged for commit in README.txt
.
Having listed all of those files, Git runs a second diff, this time to find out:
- What's different in the index vs the work-tree?
Here, any file that's different, Git tells you that there is something not staged for commit. That's because you could run git add
on that file, to copy it into the index.
If you were to run git commit
right now, Git would make the new commit from whatever is in the index right now, so HEAD
-vs-index tells you: these files would be different, in this new commit, from what's in the current commit. Meanwhile index-vs-work-tree tells you: these files could be different, but won't be unless you git add
them.
This second diff is also the step that discovers any untracked files. An untracked file is, quite simply, a file that's in the work-tree, but not in the index. If such a file is ignored, Git shuts up about it. If the untracked file is not ignored, Git tells you that it is untracked. Note that a file that is in the index is by definition tracked, so Git never even checks for an ignore directive.
This fact—about new / untracked files—is why there are up to three copies of each file. If you create a new file, it's not in the HEAD
commit at all. It's also untracked until you git add
the file to copy it into the index. So you start out with one copy, in the work-tree only; then you have two, in the index and work-tree. Then you make a new commit, which becomes the current (HEAD
) commit, and only then are there three copies of that new file.
git add <filename>
, Git simply copies the work-tree version into the index, so now the index copy matches the work-tree version. These are the two most common situations: matches HEAD or matches work-tree. (If HEAD and work-tree copies match, the index copy can and usually does match both.) Whatgit add -p
is for is to take whatever's different between work-tree copy and index copy, and add some of that difference to the index copy. This leaves the work-tree version alone! It only patches the index copy. – Closetgit reset -p
, so I'll delete that comment. – Closet