Why is git commit -a sometimes required instead of git commit?

Playing with Git and GitHub, I found that sometimes

git commit -a 

needed to commit the file that has been modified. (this file has already been added to the project).

But sometimes just

 git commit 

will work. If you use Mercurial, the hg com command always works if it is a file that has already been added to the repo before. So I wonder why git is required -a sometimes? The word "statement" appears in some explanation, but I do not quite understand the concept of statement and how is it related to fixing some changes in the file?

+4
source share
5 answers

Suppose you made two different logical changes to a file, but only want to commit one of them. If "git commit" always transferred all the files that he knows about, this action would be impossible. Thus, you need to generate each change before committing. If you "git add file name", you create all changes to this file. BTW, "git stage" is synonymous with "git add", and it can make actions clearer if you use "git stage" instead.

Think of the staging area (index) as the staging area between your working directory and the repository. The git add and git stage commands move objects to the index, and git commit move them from the index to the repository. "git commit -a" performs both actions at the same time. It is often very useful to be able to use the stage to help improve your commits so that you commit exactly what you want.

+2
source

A detailed review of the git commit man page describes it:

  • when you add a new file to git, you do it with git add . This means that the file will be added after the next commit (as well as git rm to delete the files).
  • when you change the file, you can also do git add to mark it for the next commit, but usually you don’t. In this case, git commit -a works for you:

    Tell the team to automatically create files that have been modified and deleted, but new files that you did not tell git about are not affected

Example: if you want to commit only with some changed files (for example, you fixed a bug affecting two files ( one.c , two.c ) and deleted some typos in other files and want the bugfix check to be separated from the check typo), you must do git add for each of the patch files and then commit:

 git add one.c git add two.c git commit -m "bugfix checkin" 

Once this is done, you will fix typo corrections using

 git commit -a -m "fixed typos" 

Regarding the stage:
git commit only commits files that were marked in some way for commit. This can happen, for example, through git add or git rm . This marking for fixation is called staging.

+1
source

See also the article “ You could come up with git (and maybe you already have one!) ”: This helps when you think of the index as a “patch database” .

If you "added" a file (to the "index", also known as the "setting area"), you are actually adding a patch represented by the evolutions made in this file.
If you added new changes to one file after adding to the index, you are actually making a new patch (with all the new changes since the last " git add "), and these new developments need to be added (to the index, the "database of patches" ) before you can commit. Or you can just do git commit -a in this case.

+1
source

To understand the difference between git commit and git commit -a , you need to know about index in git, also known as staging area .

In the main index, the state of each file is saved, which will go to the next commit. (By “state” here I mean the exact contents of a file that git identifies by its hash.) When you enter git commit without any other parameters, git will do a new git commit in which the states of all files are exactly the same as in the index. This can be very different from your working tree and the useful git function, as I will explain below.

What git add really does is "stage" the file or add its current state to the index. It doesn’t matter whether it was initially tracked or not, you say "in the next commit, I want this file to be present with this particular content." It’s important to understand that this writes the content that you want to add, not the file name — this means that if you continue to make changes to the file after you put it with git add , you will see the output from git status , which sometimes confuses people coming from other version control systems:

 $ git status [...] # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # modified: foo.txt # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: foo.txt 

... but it makes sense if you know about the index. You can see the changes that you have already made (i.e., the difference between the state of the files in the index and HEAD, which is usually the last commit in the branch you are working on):

 $ git diff --cached 

... and you can see all the changes that have not yet been made (i.e. the difference between your working copy and index):

 $ git diff 

So why is it so helpful? In essence, the idea is that the history of your project is most useful when each commit contains only a logically grouped set of changes that provide a well-defined improvement to the project. The less you can make these commits, the better, as later on, the wonderful git bisect tool can quickly help you keep track of which change has made an error. If you are not extraordinarily disciplined, during the error correction process you will often edit other files that you really do not need to fix this problem, or may ultimately fix two logically different problems before deciding to make your changes. In these cases, the index can help you highlight these changes - just git add each file containing the changes you want in the first commit, run git commit , then do the same to create the second commit. [1]

If you get used to it as a workflow, you will eventually just want to make some changes to the file, not others, in which case you will want to learn about git add -p (and then its interactive options s and e !)

However, to get back to the original question - what does git commit -a do something else? Essentially, he says: "Before creating this commit, also create every file that has been modified (or deleted) in its current state." So, if you do not think that you need to carefully process the files in the index before committing, you can just use "git commit -a" all the time. However, I think one of the nice things about using git is that it encourages the creation of beautiful commits, and actively using this index is a big help for that. :)


Notes:

To simplify the above explanation, some statements are somewhat approximate (for example, I did not mention that the index also preserves the (un) executable state of the file, that it can have several versions during merging, etc.).

[1] You have to be careful if you want to make sure that every commit in your story has been checked correctly - if this is important in your project, you should test the tree with every new commit before clicking ...

+1
source

Check out the faq . In short, it makes git more flexible.

0
source

Source: https://habr.com/ru/post/1341958/


All Articles