2

I get an unexpected appearance of "dev/null" in my git status output after interactively adding a patch for a file that was renamed. I'm wondering if this is expected and there is some good reason for this behavior, or if this could be a bug.

Below is a simple illustration of how to reproduce this. In my real-world scenario, it's a bit more complicated and there's a good reason why I'm using git add -p, but I was able to boil it down to this minimal example:

 $ git init test Initialized empty Git repository in /local_disk/tmp/test/.git/ $ cd test $ echo "foo" > foo $ git add foo $ git commit -m 'Add foo' [master (root-commit) 3643b5d] Add foo 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 foo $ mv foo bar $ git add -p diff --git a/foo b/foo index 257cc56..0000000 --- a/foo +++ /dev/null @@ -1 +0,0 @@ -foo Stage this hunk [y,n,q,a,d,/,e,?]? y $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: dev/null # deleted: foo # # Changed but not updated: # (use "git add/rm ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # deleted: dev/null # # Untracked files: # (use "git add ..." to include in what will be committed) # # bar 

What is with the "new file: dev/null" and "deleted file: dev/null"? I would expect this to result in exactly the same thing as if I had done:

 $ mv foo bar $ git rm foo $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # deleted: foo # # Untracked files: # (use "git add ..." to include in what will be committed) # # bar 

I am using Git version 1.6.5.5, and have also reproduced it in 1.6.5.4. I was unable to reproduce it in my Cygwin environment which has Git at version 1.6.1.2.

5
  • what version git? I can't repeat that behavior. Instead, git add -p after git mv responds: no changes Commented Dec 7, 2009 at 18:38
  • @William: Using git mv is not equivalent, because it moves and adds the file at the same time. I am moving the file using just plain mv, and then using git add -p to add it. Commented Dec 7, 2009 at 18:46
  • @Dan, why? git mv is the 'proper' way to change a file's name. To delete a file you use git rm and to move one you use git mv, don't just move the file yourself and expect git to read your thoughts :) Commented Dec 7, 2009 at 18:52
  • @thenduks: I don't believe that's true. git mv, if I'm not mistaken, was added to appease the crowds that were clamoring for such a command. It doesn't do anything that simply moving the file and then adding it would do. git, in fact, does read your mind (well, actually it examines the differences and identifies the rename on its own). Git doesn't need, or want, you to tell it about such things. Commented Dec 7, 2009 at 18:57
  • Read your example many times, and each time I looked at 'mv foo bar' I read 'git mv foo bar'. Odd. Anyway, as a workaround, if you invoke 'git add dev/null' after you run add -p you get the behavior that you want. Commented Dec 7, 2009 at 19:54

1 Answer 1

2

As thenduks mentions, you shouldn't be trying to git add the file removal. git add the new file, git rm the old file (or git mv old new to take the simple approach). On the other hand, git should either complain about what you're doing or not get confused and try to add a non-existent dev/null file.

Update
git add -p is indeed a valid method to stage file removals, but it looks like a bug was introduced to git apply when fixing a different git apply bug.

Update
I can reproduce it on Linux with 1.6.1.2, so it may be that the cygwin git is what differs from the normal behavior. In that case, the previously mentioned bug-fix may not have introduced this behavior and the working git add -p may be specific to cygwin's git. I've been trying to bisect to find where git add -p started failing.

Update
Turns out it was rather a bug in the interactive aspect of git add which Jeff King has proposed patches for.

Sign up to request clarification or add additional context in comments.

13 Comments

Like I said in my question, this is a simplified "boiled-down" example. In my real-world scenario, git add -p was used because it's a bit more complicated (some changes I want to have staged, and some I don't). Git normally allows "removing" content by using git add -p. git rm is not required to do this, it's just a convenient way of telling git that you'd like to "add the removal" of a (no longer existing) file to the index. If it were incorrect to do this, then git add -p wouldn't offer to stage patches that remove content.
Put another way, let's say I have 100 files that I've removed, but I only want to commit the removal of 50 of them. git add -p would be a very convenient way to quickly say 'y'/'n' and go through the list of files to choose which removals should be staged for the commit.
git rm is needed to stage file removal. You can verify that by trying to do git add deletedFile. Nothing happens. This is why I say that git add -p should complain or not do anything when you use it to stage a file removal. git mv is indeed a convenience command, but git rm is not.
The reason you can't git add foo if foo has been deleted is because foo is no longer a file in the filesystem, so Git has no way of knowing what you are trying to do (i.e. did you mistype the filename?). However, there are other ways of letting Git know that you'd like to stage (add to the index) the removal of foo. git rm is one way, git add -A is another, git add -i is yet another. In fact, this is exactly what all the variants of the git add command do. I'm sure if you look at git add and git rm you'll probably find they use the same plumbing underneath the porcelain.
Except that when you do git add unknownfile you get an error about the unknown pathspec. That isn't the case when there's a known file that has been removed from the working copy.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.