5. Handling Changes

5.1. Procedure

When we’re talking about “committing changes”, we mean adding changes to the local Git repository. This is achieved in 2 separate steps:

../_images/staging_area.svg
  1. Changes are staged, which means they’re added to a staging area

  2. The changes in the staging area (i.e. changeset) are then committed to the local Git repository

Hint

This 2-step procedure with the staging area helps us to bundle different changes (e.g. file content changes) into a complete changeset, which can then be committed as a commit.

Unstaged changes are will not be committed to the repository at that point. However, they stay in place and will not be affected (e.g. deleted, reverted or alike).

5.2. File Lifecycle

Each file will go through different lifecycles, which are crucial to understand when working with Git commands:

../_images/lifecycle.svg

First of all, Git makes a distinction between the following two “global states”:

  • Untracked: Files which were not added to the Git repository (yet)

  • Tracked: Files which are tracked by Git, because they were added to the Git repository before

The tracked files can have one of the following states:

  • Unmodified: File wasn’t modified since last commit

  • Modified: File was modified since last commit, but not added to the staging area

  • Staged: File was modified since last commit, and added to the staging area

5.3. Status

To check the status of your files, the following command can be used:

git status

When there are no open changes, the command will output something like this:

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

When you start working, a more realistic output can be something like this:

On branch my-feature
Your branch is ahead of 'origin/my-feature' by 4 commits.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   path/to/a/modified/staged/file.txt
        new file:   path/to/a/new/staged/file.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   path/to/a/modified/file.txt
        modified:   path/to/another/modified/file.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        path/to/an/untracked/file.txt

Hint

Please note the different 3 sections above (staged, unstaged & untracked).

Git’s also your buddy, because it will tell you which commands you need to do certain actions directly in the git status output.

5.4. Stage Files & Folders

To stage new files, use the following command:

git add {FILE OR DIRECTORY}

Hint

You don’t need to specify -r for a directory or alike.

5.5. Stage Patch Hunks

Git also allows you to add only hunks of patches to the staging area. This feature can be used if you did multiple changes in a single file, but you only want to commit a subset of it.

To add only hunks to the staging area, use the following command:

git add -p {FILE OR DIRECTORY}

Git will then open up your preferred CLI editor, shows you a single hunk and asks you to make a decision:

(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?

The explanation of the letters can be shown by putting in a question mark ?:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
g - select a hunk to go to
/ - search for a hunk matching the given regex
e - manually edit the current hunk
? - print help

5.6. Restore Files & Folders

To restore a modified (unstaged) file or folder, use the following command:

git restore {FILE OR DIRECTORY}

In case the file is already staged and you want to unstage it, use this command instead:

git restore --staged {FILE OR DIRECTORY}

Hint

The git restore command was introduced with Git 2.23.0. Before that, git reset respectively git checkout was used.

5.7. Diff

To see what you’ve changed but not yet staged, use the following command:

git diff

In case you want to see the staged changes, use the following command:

git diff --staged

5.8. Commit

When you’re happy with your staged changes (see Status), you can commit this changeset. This is usually achieved by the following command:

git commit

When hitting enter, this will open up an editor in which you can enter the Git message. You can also use the shortcut and define the message on the CLI itself. This works, but I wouldn’t recommend it:

git commit -m {MESSAGE}

Important

Remember to write a decent message, as described in A Proper Message.

Hint

If you want to change the editor, have a look at the Editor config.

5.9. Ignore Files

You can ignore files in Git which results in:

  • The files not showing up in the Status

  • The files can’t be committed

Hint

This is usually done with files which should not end up in the repository, such as:

  • OS files (e.g. .DS_Store, .Trash, )

  • Caching files (e.g. *.pyc, __pycache__/)

  • Built files (e.g. build/, .venv)

To ignore files, add file & directory patterns to the .gitignore file in your repository.

The rules for the patterns you can put in the .gitignore file are as follows [1]:

  • Blank lines or lines starting with # are ignored.

  • Standard glob patterns work, and will be applied recursively throughout the entire working tree.

  • You can start patterns with a forward slash (/) to avoid recursivity.

  • You can end patterns with a forward slash (/) to specify a directory.

  • You can negate a pattern by starting it with an exclamation point (!).

Note

After completing this chapter, you should be able to execute the Committing Is Fun exercise.