When recording your own work, the contents of modified files in
your working tree are temporarily stored to a staging area called
the "index" with git add. A file can be reverted back, only in
the index but not in the working tree, to that of the last commit
with git restore --staged <file>
, which effectively reverts git
add and prevents the changes to this file from participating in
the next commit. After building the state to be committed
incrementally with these commands, git commit
(without any
pathname parameter) is used to record what has been staged so
far. This is the most basic form of the command. An example:
$ edit hello.c
$ git rm goodbye.c
$ git add hello.c
$ git commit
Instead of staging files after each individual change, you can
tell git commit
to notice the changes to the files whose contents
are tracked in your working tree and do corresponding git add
and
git rm
for you. That is, this example does the same as the
earlier example if there is no other change in your working tree:
$ edit hello.c
$ rm goodbye.c
$ git commit -a
The command git commit -a
first looks at your working tree,
notices that you have modified hello.c and removed goodbye.c, and
performs necessary git add
and git rm
for you.
After staging changes to many files, you can alter the order the
changes are recorded in, by giving pathnames to git commit
. When
pathnames are given, the command makes a commit that only records
the changes made to the named paths:
$ edit hello.c hello.h
$ git add hello.c hello.h
$ edit Makefile
$ git commit Makefile
This makes a commit that records the modification to Makefile
.
The changes staged for hello.c
and hello.h
are not included in
the resulting commit. However, their changes are not lost — they
are still staged and merely held back. After the above sequence,
if you do:
$ git commit
this second commit would record the changes to hello.c
and
hello.h
as expected.
After a merge (initiated by git merge or git pull) stops because
of conflicts, cleanly merged paths are already staged to be
committed for you, and paths that conflicted are left in unmerged
state. You would have to first check which paths are conflicting
with git status and after fixing them manually in your working
tree, you would stage the result as usual with git add:
$ git status | grep unmerged
unmerged: hello.c
$ edit hello.c
$ git add hello.c
After resolving conflicts and staging the result, git ls-files -u
would stop mentioning the conflicted path. When you are done, run
git commit
to finally record the merge:
$ git commit
As with the case to record your own changes, you can use -a
option to save typing. One difference is that during a merge
resolution, you cannot use git commit
with pathnames to alter the
order the changes are committed, because the merge should be
recorded as a single commit. In fact, the command refuses to run
when given pathnames (but see -i
option).