Overview
Teaching: 10 min
Exercises: 10 minQuestionsObjectives
- What should be included in a single commit?
- What is the git staging area? What commands use it?
- Learn how to tell a story with your commit history.
- Demystify the Git staging area.
Your current code is very important, but the history can be just as important - it tells a story about how your code came to be.
Along with your code, git creates a history for you, and if your history is clear then you are a long way to organized code.
Discussion
Here are four types of history. What are the advantages and disadvantages of each, when you look at it later?
Example 1 (newest commit is on top):
b135ec8 add features A, B, and C
Example 2 (newest commit is on top):
6f0d49f implement feature C fee1807 implement feature B 6fe2f23 implement feature A
Example 3 (newest commit is on top):
ab990f4 saving three months of miscellaneous work I forgot to commit
Example 4 (newest commit is on top):
49dc419 wip (work in progress) 61dd3a3 forgot file and bugfix 72e0211 another fix to make it compile 72d78e7 feature A did not work and started work on feature B bddb280 more work on feature B and make feature A compile again 45831a5 removing debug prints for feature A and add new file bf39f9d more work on feature B b135ec8 now feature A should work
Example 5 (newest commit is on top):
1949dc4 Work of 2020-04-07 a361dd3 Work of 2020-04-06 1172e02 Work of 2020-04-03 e772d78 Work of 2020-04-02
Discuss these examples. Can you anticipate problems?
We want to have nice commits. But we also want to “save often” (checkpointing) - how can we have both?
git commit -p
and/or the staging area.git commit -p
option.git commit -p
to start the interactive commity
to use the changen
to skip the changes
(split) if there are several changes grouped together, but
separated by a blank line, split them into separate choices.q
aborts everything.?
for more options.-p
option is also available on commit
, checkout
, reset
, and add
.Interactive committing
One option to help us create nice logical commits is to stage interactively with
git commit -p
:
- Make two changes in in
instructions.txt
, at the top and bottom of the file. Make sure that they are separated by at least several unmodified lines.- Run
git commit -p
. Using the keystrokes above, commit one of the changes.- Do it again for the other change.
- When you’re done, inspect the situation with
git log
,git status
,git diff
andgit diff --staged
.- When would this be useful?
Analogies to the staging area
We give two examples and the instructor can pick one or both:
- Analogy using moving boxes
- Analogy using shopping receipts
Analogy using moving boxes
- You’re moving and you have a box to pack your things in.
- You can put stuff into the box, but you can also take stuff out of the box.
- You wouldn’t want to mix items from the bathroom, kitchen and living room into the same box.
- The box corresponds to the staging area of Git, where you can craft your commits.
- Committing is like sealing the box and sticking a label on it.
- You wouldn’t want to label your box with “stuff”, but rather give a more descriptive label.
Analogy using shopping receipts
- You need to go shopping and buy some stuff for work and for home. You need two separate receipts.
- Bad idea: go through the store get home stuff, pay, start at the beginning and go through the store again. This is inefficient and annoying.
- What you actually do:
- Go through the store and put everything you need in your shopping basket.
- Get to the checkout. Put your home stuff on the conveyor belt (
git add
). Check both the belt (git diff --staged
) and your basket (git diff
) to make sure you got all your home stuff.- Pay (
git commit
)- Repeat for work stuff.
In order to keep organized, you have to use multiple locations to stage things in sequence.
With the staging area, there is one middle point before commits.
Files can be untracked, modified, staged, or committed, and 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
# in latest Git: git restore --staged <path>
$ git checkout <path> # check out the latest staged version ( or committed
# version if file has not been staged )
# in latest Git: git restore <path>
Usage 1: you do various things at once
git add
all the parts of each change.git diff
and git diff --staged
to ensure you have all the parts.git commit
.Usage 2: you want to checkpoint
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).Note: the “staging area” has also alternatively been referred to as the index and the cache.
$ 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
# ... further work on another_file.py ...
$ 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
Exercise: Using the staging area
- In your recipe example, make two different changes to
ingredients.txt
andinstructions.txt
which do not go together.- Use
git add
to stage one of the changes.- Use
git status
to see what’s going on, and usegit diff
andgit diff --staged
to see the changes.- Feel some regret and unstage the staged change.
Test your understanding
- When is it better to “save” a change as commit, when is it better to “save” it with
git add
?- Is it a problem to commit many small changes?
- What types of problems can occur in other version control systems without a staging area?
Key Points
The staging area helps us to create well-defined commits.