git add
vs git commit
We have been using git add
every time we want to
commit a change, separate from git commit
. Why? We will demystify this now,
and learn how to keep organized.
Git forces you to create version history and commit messages, and if these are clear then you are a long way to organized code.
Bad example:
b135ec8 now feature A should work
72d78e7 feature A did not work and started work on feature B
bf39f9d more work on feature B
49dc419 wip
45831a5 removing debug prints for feature A and add new file
bddb280 more work on feature B and make feature A compile again
72e0211 another fix to make it compile
61dd3a3 forgot file and bugfix
There are multiple things that are not so stellar in this version control history.
Good example:
6f0d49f implement feature C
fee1807 implement feature B
6fe2f23 implement feature A
We want to have nice commits. But we also want to “save often” (checkpointing) - how can we have both?
git add
). Check both the belt (git diff --staged
) and your
basket (git diff
) to make sure you got all your home stuff.git commit
)In order to keep organized, you have to use multiple locations to stage things in sequence.
Just like the shopping example, files can be untracked (still on the shelf), modified (in your basket), staged (on the conveyor belt), or committed (paid for).
We have a variety of commands to go between states:
$ git add <path> # stages all changes in file
$ git add -p <path> # stages while letting you choose which lines to take
$ git commit # commits the staged change
$ git diff # see **unstaged** changes
$ git diff --staged # see **staged** changes
$ git rm # removes a file
$ git reset # unstages staged changes
$ git checkout <path> # check out the latest staged version ( or committed
# version if file has not been staged )
git add
every change that improves the code.git checkout
every change that made things worse.git commit
as soon as you have created a nice self-contained unit (not too large, not too small).$ git add file.py # checkpoint 1
$ git add file.py # checkpoint 2
$ git add another_file.py # checkpoint 3
$ git add another_file.py # checkpoint 4
$ git diff another_file.py # diff w.r.t. checkpoint 4
$ git checkout another_file.py # oops go back to checkpoint 4
$ git commit # commit everything that is staged
git diff
gives differences with respect to the staging area, this is very practical.git add
we can create very nice coherent commits.-p
option gives you even more control, and as a bonus shows you the diffs as you stage/reset/checkout things.ingredients.txt
and instructions.txt
which do not go together.git add
to stage one of the changes.git status
to see what’s going on, and use git diff
and git diff --staged
to see the changes.Sometimes you want to stage all modifications but not add any new files. No need to stage them one by one:
$ git add --update
Also removals of tracked files are then automatically staged.
Some people accept that there will be many small commits. Some people
are very obsessive about clean history and constantly use rebase
to
make it clean.
Below are some alternatives, from easiest to hardest. Don’t worry about understanding them all, this is one of the last lessons so we just try to show you some dreams
Use git commit -p
.
You can use git commit -p
on unstaged changes to directly commit.
This is a convenient short cut, but if you notice something wrong as
you are committing, you have to start over again. Still, if you are
doing simple things, it can be useful. Check git show HEAD
and git
diff
when done to make sure things are OK.
You could use lots of temporary branches. It’s more explicit but can get annoying. Then, you can use rebase to squash all of the commits together.
You can make lots of small commits on a branch and then rebase them to squash them together into one commit. We don’t go into the details of rebasing because there is more that can go wrong. This is fairly advanced, but GitHub and other sites allow you to automatically do this.
Note: the “staging area” has also alternatively been referred to as the index and the cache.
git diff
and git checkout <path>
to get a feel for checkpointing.git diff
and git checkout <path>
are with respect to staged changes.git diff
, try also git difftool
.git add
?The staging area helps us to create well-defined commits.