Git offers developers a range of features to provide powerful versioning for software projects. Git protocols come with many features and can often feel overwhelming. The -a`
flag automatically stages files that have been modified or deleted to help improve workflow efficiency.
This option does not affect any files that Git is not aware of yet, however. In this short article, we’ll take a look at setting up a basic project with git-mediated versioning and demonstrate the impact of the -a
option. Some familiarity with Git will be assumed but all steps will be outlined clearly.
Note: The -a
option is used in this tutorial but can also be passed as -all
while providing the same functionality.
Quick Intro: Setting up a Git Project
To demonstrate the use of the -a
option in Git, we’ll set up a sample project, initialize Git, add our files, make some changes, add those again, and compare the differences. You will need to have Git installed to follow along. Our steps will be as follows:
- Create a sample project with a root directory, sub-directories, and sample files containing some amount of random data.
- Initialize Git in our sample project.
- Use the add, commit, and commit -a commands.
A sample project, complete with sample sub-directories containing sample files with sample content will be created using the create_sample_project.py
script (available on Github) that reflects the following structure:
. └── sample_project/ ├── sample_dir_0/ │ ├── sample_file_0_0.txt │ ├── sample_file_0_1.txt │ └── sample_file_0_2.txt └── sample_dir_1/ ├── sample_file_1_0.txt ├── sample_file_1_1.txt └── sample_file_1_2.txt
Here we see a root directory, two sub-directories, and 3 files within each subdirectory. Each sample file contains a random string of ASCII characters so that Git can detect changes later. From sample_file_0_0.txt
:
AFEcZwbWrMVtrwMQEDgebMIfIbZoFNGVUsVUrvASSWnYNrQZFcUBYFRlwgNZxTjZJCvzFUbKyaExqbKlbduAWnhsrGeGLaXhdZxEyPHeQHXSGIWdnfhBppvxGErlAxzzybwQSxTYdtwvAbnGyWwCRyBIeOqamwRbDpImFHaFnUerhsPOFysqwGoiBdphdcUqSojdBLMbWKbTiRqfcmvEiKxjyhXooUAylbGZpFMYWnLTVcPxIJiEKPYPzgMBOlqd
Nothing special here, just 256 random ASCII characters. Next, we’ll initialize Git in our directory by running the git init
command as follows:
$ git init // output Initialized empty Git repository in /path/to/the/sample_project/.git/
The git status
command will provide information related to the current state of version tracking in this sample project:
$ git status On branch master No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) sample_dir_0/ sample_dir_1/ nothing added to commit but untracked files present (use "git add" to track)
The last line is very telling and hints that no files are currently being tracked. If the git commit
command is run, a very similar message will be displayed. Taking the advice of Git’s messaging system, the git add sample_dir_0/*
command will notify git about all files in sample_dir_0
and begin tracking those. Re-running the git status
command now displays the following to the terminal:
$ git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: sample_dir_0/sample_file_0_0.txt new file: sample_dir_0/sample_file_0_1.txt new file: sample_dir_0/sample_file_0_2.txt Untracked files: (use "git add <file>..." to include in what will be committed) sample_dir_1/
This indicates that all files in the sample_dir_0
directory are being tracked and that there are still un-trakced files in the sample_dir_1
directory.
Git commit -a
The -a
option passed to the commit
command is described in the official git documentation as follows:
Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.
“Staging” a file means preparing it for a commit command and resulting push
if working with a remote repository. When the commit
command is issued, Git will add changes to any files on the “stage” which have been added via the add
command at some point. Currently, this includes all files in the sample_dir_0
directory.
Commit Files in sample_dir_0
The commit
command requires that a message is provided indicating what changes were made. Using the -m
flag will prevent the default text editor from opening (VIM in the case of most Unix-based systems.) This will add all changes from files currently added to the stage (files in sample_dir_0
):
$ git commit Aborting commit due to empty commit message. $ git commit -m "initial commit" -v // output, via the -v flag [master (root-commit) d185b55] initial commit 3 files changed, 3 insertions(+) create mode 100644 sample_dir_0/sample_file_0_0.txt create mode 100644 sample_dir_0/sample_file_0_1.txt create mode 100644 sample_dir_0/sample_file_0_2.txt $ git status // output On branch master Untracked files: (use "git add <file>..." to include in what will be committed) sample_dir_1/ nothing added to commit bu untraced files present (use "git add" to track)
Here the -v
option (verbosity) outputs all files that have been updated in this commit. To followup, the git status
command indicates that there are untracked files in the sample_dir_1
directory — because those files weren’t included in the the git add
command earlier.
Commit Files in sample_dir_1
The simple version of using git commit -a is that it will “commit all changed files.” Unfortunately, Git does not automatically add previously untracked files via the -a
option. It will only automatically add changes from currently tracked files and deleted files that were previously tracked. Running the git commit -a -m "second commit" && git status
command will produce the following:
On branch master Untracked files: (use "git add <file>..." to include in what will be committed) sample_dir_1/ nothing added to commit but untracked files present (use "git add" to track)
In other words; files in sample_dir_1
were not staged or committed. However, if we open the file sample_dir_0/sample_file_0_0.txt
and alter its content, the git status
command will now produce the following output:
$ git status // output On branch master 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: sample_dir_0/sample_file_0_0.txt Untracked files: (use "git add <file>..." to include in what will be committed) sample_dir_1/ no changes added to commit (use "git add" and/or "git commit -a")
This message indicates that in order to stage the changes made in sample_file_0_0.txt
one must do two things:
- Use the
add
command - Use the
commit
command
Using the -a Flag Correctly
In other words, staging and committing files is a two-step process. However, the -a
option allows this to happen in a single step as follows:
$ git commit -a -m "second commit" -v // output [master 92c024a] second commit 1 file changed, 1 insertion(+), 1 deletion(-) $ git status // output On branch master Untracked files: (use "git add <file>..." to include in what will be committed) sample_dir_1/ nothing added to commit but untracked files present (use "git add" to track)
Note the git status
command now reflects only the untracked files in the sample_dir_1
directory. Passing the -a
flag into the git commit
command automatically stages changes to tracked files or deletions of existing tracked files and commits them in a single step.
Final Thoughts
The git commit -a command is incredibly useful when working with multiple files. Rather than having to pass in a list of all files that should be staged, sometimes across multiple directories, one can simply add any tracked files.
Keep in mind the -a
option doesn’t stage new files that aren’t currently being tracked. This is a source of confusion for many first-time git users and can result in untracked changes if not addressed. Using the git status command can provide helpful feedback to avoid such issues.
Check out our article on adding an existing project to an empty Github repo for more insights on how to better utilize Git version controlling for your projects! Also, check out our article on how to add a new directory/folder manually to a Github repo which is deceptively difficult.