Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git add and git commit confusion

Tags:

git

I basically know the difference between a git add which means "I want to add this file to my next snapshot" and git commit which means "take the snapshot".

However, when I run git add file1 and then removing file1 from my working directory and then run git commit it will still works. Somehow the snapshot was taken while adding and not not while commiting. Am I right?

like image 754
LivBanana Avatar asked Nov 28 '20 21:11

LivBanana


People also ask

What is the difference between git add and git commit?

git add : takes a modified file in your working directory and places the modified version in a staging area. git commit takes everything from the staging area and makes a permanent snapshot of the current state of your repository that is associated with a unique identifier.

Is git add necessary before commit?

When do you use git add ? As you're working, you change and save a file, or multiple files. Then, before you commit, you must git add . This step allows you to choose what you are going to commit.


3 Answers

git commit takes the snapshot by

  • looking at the index (where you have added the file),
  • not by looking at the working tree (where you go on modifying stuff, including adding or deleting files)

See "What's the difference between HEAD, working tree and index, in Git?"

In your case, after deleting the file (but after adding it to the index), a git status would give you:

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   go.mod

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    go.mod

The file is both:

  • ready to be part of the next commit
  • locally deleted

A git restore -- <myFile> is enough to restore it locally.


The working tree (or working directory) is the tree of actual checked out files.
The working tree normally contains the contents of the HEAD commit’s tree, plus any local changes that you have made but not yet committed.


The idea is to prepare your next commit, instead of blindly putty all your current modification into one giant commits.
It is better to make small coherent commits instead of a giant one, for getting a logical history, and making future git bisect easier.

You can even stage (add to index) part of a file (interactive staging)

The OP adds:

Imagine that commit does the work of both the actual commit and add.
Let's call it the imaginary commit.
You can still do this little by little work using the imaginary commit

First: that command (which adds all and commit) does exist:

git commit -am "Let's add everything"

Second, to do "little by little", you must use git add, then commit.
A commit takes everything in the index.

like image 106
VonC Avatar answered Oct 11 '22 16:10

VonC


Actually, there is something missing from what you know.

You actually have two copies of that file when you have added it. You have the working tree copy, which is the normal file system copy that you see and edit with normal text editors and whatnot.

But, additionally you have a copy in the index. git add copies the file and its contents from the working tree into the index. This is where the actual snapshot of that particular file is made.

When you afterwards issue a git commit, the index is stored into a commit. What is, or is not, in the working tree (aka on disk) at this point is rather irrelevant. The index is all that matters.

This is why you see that the file is still being added. It was copied to the index with git add, and even if you subsequently removed it from disk, git commit used the index as the source of the commit.

The upshot of having a separate index which makes up what the next commit is going to be is that you get to decide what your next commit is going to contain, as opposed to just "all the things on my disk at the moment". Good git tools even lets you copy files with only parts of their changes into the index, so that if you made 2 or more changes to a file you get to decide if all the changes to that single file go into the next commit or just one or a few of them.

like image 30
Lasse V. Karlsen Avatar answered Oct 11 '22 15:10

Lasse V. Karlsen


You are absolutely right. Not only that, but the file is kept as it is at the moment when you add it. If you later change it and then commit, it's saved in the revision as it is at the moment when you asked for it to be added, not the current state. Same things happen for files that are modified (just in case you think it only works for new files). If you commit a file and you modify it, git will only persists it with the new content for the following revisions if you add it.

like image 2
eftshift0 Avatar answered Oct 11 '22 15:10

eftshift0