Re: Removing files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 11 Jan 2007 21:10:20 +0100, David Kågedal wrote:
> Let's assume that I have a file "foo" in my tree, that I have removed
> from my working tree (e.g. by using patch -E).

Thanks for the example, David. I think this points out several
problems with the current state of git.

>   # Changed but not added:
>   #   (use "git add <file>..." to incrementally add content to commit)
>   #
>   #       deleted:    foo
> 
> Ok, so I try to follow the instructions in the message:

Clearly "git add" is the wrong thing to recommend here, (in that it
currently doesn't update the index for a removed file). I think this
is a bug in git-status.

I also believe it would be incorrect to "fix" git-add to make it
remove files as well. Having a command named "add" whose
functionality could be to do the opposite of the meaning of that
command would be horribly confusing, (and not an improvement in the
usability or learnability of git).

>   $ git rm foo
>   fatal: pathspec 'foo' did not match any files

I think that's just a bug in git-rm and should be fixed.

> What could be the correct command for this situation.  Some suggestions:
> 
>   $ git add foo
>   $ git add --remove foo

As I said above, I think making "add" perform removal, (which is the
opposite of what "add" means) would be a very bad idea.

>   $ git rm foo
>   $ git rm -f foo

I think either of the above should be fixed to work. The "safety
check" here is an attempt to catch typos, right? Shouldn't that be
checking for the existence of the path in the index rather than in the
working tree?

There are also two other possible commands here:

$ git commit file

On the list someone recently pointed out that this didn't work for
them (after removing a file). I had thought the conclusion was that
Junio wasn't interested in doing the work to make "index skipping"
work for this case. But maybe someone else did the work already,
because this did work for me when I tested now. Did I just get lucky?
Or is this officially supported now? (I'm quite happy to see this
working as otherwise we'd be left with only "commit -a" as a
pure-porcelain way of removing files---see below.)

$ git commit -a

This was already mentioned in a separate reply. This works, but there
are a couple of problems if this were the only supported way to remove
a file:

1. It doesn't allow for a "staged" file removal, (that is removing a
   file while allowing other dirty changes to remain in the working
   tree).

2. The fact that "commit -a" commits file removal is not documented at
   all. This was pointed out to me recently by a cairo contributor who
   was quite tripped up by this aspect of "commit -a".

   What the "commit -a" documentation says is:

       4. by using the -a switch with the commit command to automatically "add" changes
          from all known files i.e. files that have already been committed before, and
          perform the actual commit.

   And as already discussed above, "add" doesn't actually updating a
   file removal into the index. And I think it would be a mistake to
   extend "add" to do removal as well, (at that point "add" would
   become little more than a synonym for update-index without the
   --add and --rm safety checks).

So what's the fix for the "commit -a" documentation? One approach is
to add more language about file removal to the description of "commit
-a". The wording proposed by Jonathan Watt is:

       4. by using the -a switch with the commit command to automatically "add" changes
          from all known files (i.e. files that have already been committed before),
          automatically remove all known files that have been removed from the working
          tree, and perform the actual commit.

That's perhaps functional, but it's getting to be a lot of language to
have to grasp for new users. The goal of the new first-class-add was
to be able to simplify the documentation of things like this. I think
that's a failed experiment.

I'd much rather see the documentation for git-commit present a list
something like the following:

  Use git commit to record changes into the repository along with a
  log message describing the changes. New files (or directories) must
  be made known to git with "git add" before they can be committed.

  The changes to be committed are identified with one of three
  different forms of the git commit command:

  1. git commit

	Without any specific file names mentioned (and without the -a
	option), commit changes from content that has been "staged"
	for this commit. Content can be staged with the "git add" or
	"git rm" commands.

  2. git commit paths...

	With a list of file (or directory) paths, commit changes from
	the working-tree content of all named paths, (remember that
	"git add" must be used before committing any new files).

  3. git commit -a

	Commit the working-tree content of all files known to git,
	(remember that "git add" must be used before committing any
	new files)

  Note that what git commits is "working-tree content" that means that
  committing file a file deletion is as simple as removing the file
  from the working tree and then using "commit -a" or "commit file" to
  commit that removal.

I've written that in a way that it should be usable as documentation
without any changes to how git currently works, (I think---let me know
if I got any of it wrong).

But I would still like to point out some things that could be
improved. First, the "(remember that 'git add'...)" phrases are quite
redundant and should really be removed. I included them here only to
point out that the way that "git add" with "commit paths..." and
"commit -a" is really fundamentally different than "git add" used for
staging with git-commit (form (1) without paths or -a).

I think that difference should be fully recognized, and that git could
be made easier to learn if it were. Specifically, I think a "git
stage" command, (a "porcelain" version of update-index) would fit into
the description of form (1) quite nicely.

Also, (and especially if the "remember" phrases are removed), note
that the three different commit commands are written in
reverse-simplicity order. That is, "commit -a", the form with the
shortest explanation (and the fewest necessary concepts), comes
last. That's also not so nice for learning. So, I think the order of
the descriptions should be reversed, (with this style of explanation
for "commit -a", there's no need to base it on an understanding of a
staged commit first).

So, what I'd like to see, (but would require the addition of "git
stage" and a slight philosophical switch in the consensus for how git
should be taught), would be:

    git commit -a

	Commit the working-tree content of all files known to git.

    git commit paths...

	Commit changes from the working-tree content of the specified
	paths.

    git commit

	Commit changes from all content that has been staged with
	"git stage".

This approach, (separating "stage" for staging into the index from
"add" for adding new paths), would also allow for "add" to be changed
to not also stage the content into the index.

I really like the simplicity of explanation that this model
provides. And I'd love to hear any feedback that anybody has about it.

-Carl

PS. And look! I even resisted the next step which would be to
recognize that the simplest-to-explain and most-common-to-use form
should have the simplest command-line syntax. That is, I didn't
suggest command-lines of:

    git commit
	...
    git commit paths...
	...
    git commit -s|--staged
	...

Attachment: pgpNGi9wyJ71j.pgp
Description: PGP signature


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]