5

I am new to Git and I am using Git extension. I want to ask that When I commit the directory Whether these file automatically go for staging or these get committed without staging?? Can I commit files without staging??

guerda
  • 23,388
  • 27
  • 97
  • 146
atul
  • 135
  • 1
  • 2
  • 8

2 Answers2

14

It's worth mentioning here that all of these methods do use an index, aka staging area, aka cache.

When Git makes a new commit, it does so using whatever is in "the index". As the phrase the index implies, there is a single, special, distinguished thing: the index, as opposed to an index. But in fact, Git can use some other index. We need to know what "the" index is, and what it means to be the index, versus some other index.

The short version is that the index is what Git uses to build up the next commit. We start out with what's in this commit, i.e., the current or HEAD commit. You run git checkout master or git checkout branch or whatever, and Git fills up your work-tree with a bunch of files. It puts the same files into the (single, special, distinguished) index, also called the staging area. This means the index/staging-area starts out full of many files: mostly, the same ones in your work-tree, where you do your work. The exception is that some work-tree files may be untracked.

An untracked file is one that is not in the index. It's really that simple: any file that is not in the index is untracked; any file that is in the index is tracked. The ones in the index start out being the same as the ones you git checkout-ed, that git checkout put in your work-tree.

You then make a bunch of changes to a bunch of files. If you run git commit right now, though, the index / staging-area still has the original git checkout versions, not the modified work-tree versions. So you have to git add the changed files to copy them into the index.

This is kind of a hassle, so Git has git add -u and also git commit -a. But both of these just look at what's in the index right now, and copy the new work-tree version of those into the index. So git commit -a -m "commit message" doesn't add files that are in the work tree but are not in the index—i.e., files that are currently untracked. This is the same as git add -u: only tracked files get updated.

Here's where it gets a little complicated

Besides the above, git commit can take path names as arguments:

git commit -m "some message" file1 file2

for instance. But this implies the --only flag, i.e., commit only changes in file1 and file2. You can also run:

git commit -m "some message" --include file1 file2

This overrides the --only.

The way all this works is that Git can use a different index, instead of the standard one. When using --only, what Git does is build a new temporary index from the HEAD commit. Then, into this temporary index, Git copies the specified files from the work-tree, replacing the old versions, or adding new files. Then Git makes a commit from this temporary index: the new commit has all the same files as the HEAD commit, except for whatever it added due to --only file1 file2.

When you use --include, Git makes its temporary index by copying the current index, instead of by extracting HEAD again. So now whatever you have git add-ed so far is in the temporary index too. Then Git adds the specified files, and makes the new commit.

In all cases, after Git makes the new commit, it has to fix up the real index too, because now you have committed the latest file1 and file2 (and maybe other updates if you used --include). If you used --include, the temporary index simply becomes the real index.

If you used --only, this is the most complicated case. Here Git copies the added files into the real index too, at this point, but otherwise leaves the real index alone. That way, whatever you staged before is still staged. The new commit has in it whatever was in the HEAD commit (via the temporary index), except for the specified files (that were git add-ed into the temporary index). And, whatever you specifically committed just now is also git add-ed to the real index now, as if you ran git add on those files.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 1
    Wow, very comprehensive. Thanks! – pfabri Feb 09 '20 at 13:08
  • This is a brilliant explanation. Interestingly, it would have been nice to see the temporary index in some way to verify the nuances of the working. – theOne Mar 10 '22 at 08:46
  • @theOne: the temporary index exists only for the duration of the one `git commit` command. You *can* see it in some ways though: for instance, your pre-commit hook is run with environment variable `GIT_INDEX_FILE` set to show the name of the temporary file (the default setup has it unset or set to the standard index). Unfortunately there's no perfect and easy way to *test* for this because `git worktree add` adds a working tree whose standard index is not `.git/index` but rather `.git/worktrees//index` for some ID, and there are no promises that this might not change someday. – torek Mar 10 '22 at 21:53
  • 1
    Meanwhile, if you use a `git commit` command that runs an editor, and use a second window or similar to poke around inside the `.git` directory while that editor is waiting for you (the human) to edit the commit message, you can find the temporary index. In the case of `git commit --only` there are in fact *three* index files active; for `git commit --include` there are two. But again these are implementation details with no real promises made. This is a bit unfortunate since it constrains what you can do in a pre-commit hook. – torek Mar 10 '22 at 21:55
  • +1 simply brilliant! I now use `git commit -m "some message" file1` to commit minor changes in `file1` (e.g. fixing whitespace) that are unrelated to the current work, and without disturbing my staging area (before reading this answer, I would unstage all the files, stage the changed `file1`, commit, then restage the previous files to continue...that was tiresome...`git commit --only` is awesome). – Eric Mutta Nov 02 '22 at 02:08
  • 1
    @EricMutta: you can even combine that with `--amend`, which boots the previous tip commit off the branch by making the new commit the tip commit of the branch (by making the new commit's parent(s) be the kicked-out-commit's parent(s)) to fix a glitch in the previous commit. But I generally find that getting too fancy is harmful, that it's better to just make a bunch of smaller commits and use `git rebase -i` to combine things and fix things up. – torek Nov 02 '22 at 02:22
12

Yes, you can stage and commit using a and m in the commit:

git commit -am "my commit message"

However, I tend to use git add -u anyway because the above command will not stage untracked files.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132