2.6.2. Committing to a local repository#

Before turning towards collaboration with a shared Git repository, let’s practice creating a new Git repository on your local computer and committing some plain text files.

In practice, a Git repository is just a directory on your computer, with a special hidden subdirectory called .git/ containing the meta-data that the Git tools use to keep track of the version information of files and subdirectories in this directory. When you execute a Git command using the git program in the shell, Git will first determine if the current working directory is a Git repository (i.e. if it contains a .git subdirectory), and if not one of the parent directories is a Git repository.

There are two common approaches to setup a Git repository on your computer,

  1. Initialize in your current working directory a new empty Git repository that is not (yet) associated with any existing repository; and

  2. Create a clone of an existing Git repository, such as from an online Git server (e.g. gitlab), as a new directory.

In this section you will initialize a new empty Git repository and commit some files. You will explore the second option in Section 2.6.4.

2.6.2.1. Initialize a new local Git repository#

Let’s first create a new directory with a file inside it, which would represent maybe some new project that we have started to work on and that we now wish to manage with Git.

Exercise 2.79

Create a new directory, with some dummy example files, e.g.

$ mkdir coolproject
$ cd coolproject
$ echo hello world >> greeting.txt
$ echo foo >> bar.txt

(If you wonder what the echo TEXT >> FILENAME commands above do, they just append the line TEXT to the text file called FILENAME, which will be created it if does not exist yet. So, these are just one-line commands to create some dummy files with content. You will learn more on the >> syntax later in Section 2.7.1.)

To initialize a new Git repository for your project directory, ensure that you are currently working inside the top-level directory of your project (coolproject/ in this case) and run git init:

Exercise 2.80

Initialize a new Git repository in the directory

$ pwd # should show your coolproject directory
$ git init

You can verify that the directory now contains a Git repository by listing its content including hidden files and directories. You should see the .git subdirectory.

    $ ls -la # should show .git subdirectory

Do not modify anything in this special .git directory or it may corrupt your repository. If however you wish to remove the Git from your current directory, it suffices to simply delete this subdirectory (with rm -rf .git as discussed in removing directories).

The repository still does not track any files inside the project directory, nor will it know about any changes to these files. We can always verify the status of the repository through git status, which should tell you the name of the Git branch that you are working up (which will be the default called master or main branch in the new repository), the most recent commit, and any tracked and untracked files.

Exercise 2.81

Get the status of the current repository:

$ git status

Verify from the status output that the files greeting.txt and bar.txt are not tracked by Git yet.

2.6.2.2. Tracking files#

Before we can make a first commit to add the files, we need to tell Gitto these files should be part of the repository, so that it will track their status and look for changes. We can inform Git which untracked files must be tracked by simply using the git add <Filename> command.

Exercise 2.82

Tell Git to track the files by adding them:

$ git add greeting.txt
$ git add bar.txt

Be aware that these Git commands will not yet create any Git commit.

Rather than adding the files individually, you could also have added both files using either git add *.txt (which means “add a files with the .txt file extension”) or using git add . (which means “add all files and subdirectories in the current directory .”).

If you now run git status again, you should see that the status output now indicates that these files are now tracked and will be added as new files to the repository on the next commit. Until the commit is made, the file contents have not been actually stored in the version history.

2.6.2.3. Making a commit#

To commit, simply use git commit, which will open a text editor (nano by default) with a temporary file where you can write the commit message. If you want to finish the commit, be sure to save the changes to this temporary file and exit the editor. If you close the editor without saving, Git will not create the commit yet, and you could for instance still git add more files before running {git commit} again.

Exercise 2.83

Make the first commit to add the staged files to the repository:

$ git commit

and add a short one-line commit message, e.g.

Initial commit with two dummy files

Be sure to save the message, and then close the editor to complete the commit.

Once the commit has been made, you should see a confirmation in the terminal that the commit was created with the new files, something like:

"COMMIT_EDITMSG" [unix] 12L, 291B written
[master (root-commit) bb4ad3e] Initial commit with two dummy files
2 files changed, 2 insertions(+)
create mode 100644 bar.txt
create mode 100644 greeting.txt

2.6.2.4. Inspecting your repositories commit log#

We can inspect the repository’s commit log and verify that it now contains one commit using git log,

Exercise 2.84

Lookup the commit history of your repository, and verify the author, date and (first line of) the commit message of your initial commit:

$ git log

There are many more options that you can give to git log, for instance to see the files with lines added or removed using

$ git log --stat

Even more, we can now verify that all files have been added, and (obviously) no new modifications have been made since this last commit by running git status again:

$ git status
On branch master
nothing to commit, working tree clean

Note that immediately executing another git commit would now not do anything, as a new commit requires you to git add at least one new file modifications again.

Important

Observe that when we created a commit as in the previous exercises, we used a two-step approach of first adding files and only then committing. In the exercise above, the moment you ran git add <Filenames> but before you ran git commit, the Git repository did actually take note of these files and any new or modified contents, as you could see with git status. In Git terminology, at the moment you added the files, their modifications since the last commit[1] were “staged”.

By staging files with git add you tell Git that you want to include any new or changed content of these files upon the next commit. Thus, when you have several modified files and are preparing a commit, you can take your time and run multiple git add commands to selectively only stage those modifications that logically fit in a single commit with a clear commit message. After you have committed several modifications, you can stage any remaining modification for a next commit.

This also means git add has basically two use cases, which are similar but not exactly the same:

  1. To start tracking files in the repository that have not been added before, otherwise Git would just ignore these files.

  2. To indicate which tracked files that have been altered since the previous commit should be included in the next commit.

Let’s now emulate what would happen once you continue working on your project after you have made some initial commits.

Exercise 2.85

Modify one of the tracked files, and test how git status can reveal any new modifications to the tracked files, e.g.

$ echo and goodbye >> greeting.txt
$ # ask git if any tracked files have been modified
$ git status

How can you see in the status report now that the file was changed?

The output should tell you greeting.txt was indeed modified, but not yet staged. A git commit will therefore still not do anything, until the modification is added to be staged.

Before we do that we can still get a more detailed look at what exactly has been modified using git diff, which shows in color output when lines have been added (in green) or removed (in red) with respect to the last commit.

Exercise 2.86

Inspect what lines have been added or removed in any tracked but unstaged files

$ git diff

This opens a colored overview of the added/removed lines. If there are a lot of changes that do not fit all in the terminal screen, then you can scroll through overview using the arrow keys.

Now try to stage the modified file with git add again to prepare a second commit.

Exercise 2.87

Stage the changes and verify that you are ready to commit
$ git add greeting.txt
$ git status # verify your changes have been staged
Note that the output of `git status` also gives you hints on how to `unstage' any files that you accidentally staged using `git restore`.
You could also get a detailed overview of what lines modifications are staged using `git diff -{}-staged`.

Instead of entering the commit message using the text editor, we can now also try to immediately complete the commit by using the git commit -m "<YOUR COMMIT MESSAGE>" syntax:

Exercise 2.88

Commit the staged changes immediately with a specific message
$ git commit -m "Add farewell to this exercise"
If everything is correct, Git now created the commit without first opening the editor.

Exercise 2.89

Verify the new commit in the log, and that there are no more unstaged changes using
$ git log
$ git status
Observe in the output of `git log` that HEAD still points to the `master` or `main` branch, and that this branch now points to your most recent commit. This pointer has been updated because you have been making commits while working on this branch.

2.6.2.5. Deleting a tracked file#

Deleting a tracked file is also considered a modification, thus once you removed a file and you want to record this in the Git version history, you still need to (perhaps counter-intuitively) git add <Filename> the name of the now non-existent file to confirm to Git that the deleted content should be staged.

Alternatively, if the tracked file is not yet removed from your directory, you can delete it and stage its removal in one go using git rm <Filename>.

Exercise 2.90

Delete a file, and then stage its removal

    $ rm greeting.txt
    $ git add greeting.txt

Remove and stage the other file in one go

    $ git rm bar.txt

Verify that the files are staged for removal using git status, and notice that the status output again gives suggestions how to restore the deleted files to their last tracked stage if you accidentally removed them (!). To confirm the deletions as part of the version history, complete the commit

$ git commit -m "Remove unnecessary dummy files"

2.6.2.6. Cloning#

In the remainder of this course you will always work (with your lab partner) on a cloned Git project from a gitlab repository that we will provide. This means that for the hand-in assignments you should actually never use git init to create a new repository as we did in this section, but git clone <SSH-URL> to work on the provided repository. You will learn to work with a cloned remote repository through the online Git tutorial in the next sections.

2.6.2.7. Wrapping up#

This completes our exercises on the basics of staging file modifications, and creating commits. Remember that you can also git add directories within your repository, which will stage all files within those directories at once. Generally, as you are learning the Git basic commands, it is good practice to often rerun git status and git log to verify the effect on your repository.

Important

Finally, note that when you are done practicing with this toy repository, you can simply delete the directory and all its content including its Git repository using rm -rf coolproject (be careful with this command, it cannot be undone!).

There is no global registry on your computer of the Git repository, so once the directory with the special .git subdirectory is removed, it is as if the repository never existed for Git. This means that it is cheap and simple to play around and create and remove Git repositories, but also that all version history is lost if there is no up-to-date clone of the repository somewhere else.