Skip to the content.

Log in to Vera using ssh and create a new directory for this tutorial (you can name it however you want but make it something informative like git_tutorial). Then make it your working directory by moving into it.

Before you start:


Part 1 - Tracking files

You and your friends are going to Norway for a ski trip in a few weeks. There are many things to organize and plan so you decide to make a list to keep track of everything you need to prepare.

Inside the unix_tutorial directory, create another directory for this ski trip.

mkdir ski_trip
cd ski_trip

Now you go ahead and create a git repository inside this directory. This will allow you to track changes to the files in the ski_trip directory. Make sure you are in /cephyr/users/YOUR_USERNAME/Vera/YOUR_GIT_TUTORIAL_DIRECTORY/ski_trip/ then initialize a Git repository (repo) inside your ski_trp directory by running:

git init

You will see some information about branch names (don’t worry about it) and a confirmation message telling you that an empty Git repo has been created. Now run ls -a to list all the files in the current directory, including the hidden ones.

You will see a hidden .git directory (you will not see it if you only run ls) that is used to store all the information about the project. Every time you save the state of your project (commit), Git basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot. If you delete the .git directory (don’t do it) you will lose the entire project’s history!

To check the current status of your project run:

git status

This command is very useful to understand what is going on (use it as often as you want). The output normally shows you a list of changes in the project and suggests you what to do with those changes. Right now the repo is empty so the output won’t tell you much.

Let’s create a file in which you will list the things you need for the ski trip.

nano equipment.txt

Adding a few items to the file, for example:

- skis
- boots
- helmet
- goggles

Then save [Ctrl]-s and close [Ctrl]-x the file.

How is this file handled by git? Take a look at the current status of the repo:

git status

Git detects the new file as untracked, this means that that it is not keeping track of this file yet. You can tell Git to start tracking it with the git add command.

git add equipment.txt

Check what happened with git status.

The file has been added to the staging area, to actually record a snapshot of the file you need to commit what’s in the staging area:

git commit -m "Start planning ski trip"

Note Everything that is to be tracked needs to pass through the staging area before being committed. While this seems tedious, it allows you to choose which changes to commit at any given point. If you think of Git as taking snapshots of changes over the life of a project, git add specifies what will go in a snapshot (putting things in the staging area), and git commit then actually takes the snapshot, and makes a permanent record of it (as a commit) inside the special .git directory. This allows us to commit our changes in stages and capture changes in logical portions rather than only large batches. You can bypass it by saying git commit --allhowever, it’s almost always better to explicitly add things to the staging area, because you might commit changes you forgot you made.

If you want to add all changes made to the repo or add all untracked files, run git add --all.

Always remember to commit as little as sensible in one go. It will save people headaches in the future, especially when you’re modifying an existing repo, with lots of files and data.
For instance, if you change several files, you should commit each file separately (unless it’s critical that these changes be synchronized). This helps in at least 3 situations:

The staging area is now cleared and if you run git status again it should tell you that there is nothing to commit.

Now that the current state of the project is saved, you can always compare future states to this one or come back to it.

To get the list of all commits made to a repository in reverse chronological order run:

git log

For each commit it will show the commit’s unique identifier, the commit’s author, when it was created, and the log message Git was given when the commit was created.

You can print a shorter version using:

git log --oneline

And if you only want to see the last k commits, run:

# Replace <k> with how many recent commits you want to see.
git log -n <k>

Sometimes this output can be very long and Git will display this text through a program that allows scrolling vertically through the whole output (using up/down keys). You will notice when this happens since at the bottom of the screen you will see a : prompt, not the bash terminal. Press q to quit this scrollable display and return to the command line.

We are not gonna cover it in this tutorial, but if you will work with branches you can use the > --graph flag to visualize the commit history as a branching tree. You can still try running git log --graph but the output is gonna be very similar to the simple git log for this tutorial (if needed, press q to exit). ___

Part 2 - Making changes

Your ski trip is next week and the weather forecast says it will be very cold. Add some warm clothes to your packing list.

Keeping track of new work

Open the file with nano, add gloves and wool socks to the list, then save and exit the editor. You can check your updated file using cat, it should look something like this:

- skis
- boots
- helmet
- goggles
- gloves
- wool socks

How has this change affected the state of the repo? Run:

git status

You will see that Git lists equipment.txt as modified.

To compare the current working directory status with the latest commit you can use git diff. If you don’t specify a file when running the command, by default it will show differences for all files that have changes in the working directory compared to the latest commit. To limit the diff to a specific file (or files), you can include the filename(s) as arguments.

This command is useful when you want to:

In the output you will see:

### EXAMPLE OUTPUT
diff --git a/file.txt b/file.txt
index abc123..def456 100644
--- a/file.txt
+++ b/file.txt
@@ -1,2 +1,3 @@
 Hello, world!
 This is the second line.
+This is the third line.
  1. Header information
    • diff –git a/file.txt b/file.txt → Indicates the comparison between two versions of file.txt.
    • abc123 → Hash of the committed version.
    • def456 → Hash of the working directory version.
    • 100644 → File permissions (regular file, read/write).
  2. File versions
    • — a/file.txt → The committed version.
    • +++ b/file.txt: → The current working directory version.
  3. Line changes
    • -1,2 → The original file had 2 lines starting at line 1.
    • +1,3 → The modified file now has 3 lines starting at line 1.
    • +This is the third line. → A new line was added (indicated by the +).

Now look at the differences between the current version of the equipment.txt file and the latest commit by running:

git diff

or

git diff equipment.txt

After reviewing the changes, it’s time to record them. Add the file to the staging area and then commit along with a commit message:

git add equipment.txt
git commit -m "add warm clothes"

Now that you have committed, inspect the log:

git log

To compare any current file to its state in a specific commit, give that revision ID (long alphanumerical sequence) as a parameter to the git diff command, as below. Note that your IDs will be different.

git diff cba07232cbdb53fd8d707aa79d56e2e0a340a71b equipment.txt

You can also use only the shorter version showed by git log --oneline

git diff cba0723 equipment.txt

You receive a message from one of your friends that is coming with you on this ski trip. They read in the AirBnB’s description that there is a sauna. Add swimsuit to the packing list!

By now you should know the drill: modify, add and commit. You can run git status after each command to check what’s happening.

  1. Modify the file to add swimsuit to the packing list, save and exit the editor.
     nano equipment.txt
    
  2. Add the updated file to the staging area.
     git add equipment.txt
    
  3. Commit along with a commit message.
     git commit -m "YOUR COMMIT MESSAGE"
    

Reverting changes

It’s the day before your ski trip and you get a message from you AirBnB host: unfortunately the sauna is broken (˙◠˙). This means that you will not need your swimsuit and you can remove it from your packing list.

We should then revert the equipment.txt file to one of its previous versions using the git checkout <commit ID> <file>. This command updates the working directory version of the specified file to match its state in the given commit.

Visual example

Before running the git checkout command the <file> matches the version in *Commit 3. Here’s how the repository looks like before checking out the file:*

o  Commit 3 (HEAD -> main)  <-- Current commit
|
o  Commit 2
|
o  Commit 1

After you run the command:

git checkout <commit-2> <file>
  1. The working directory version of <file> is replaced with its state from *Commit 2.*
  2. The file is automatically staged
  3. git status will show that the <file>file has been modified.
  4. The commit history remains unchanged.
    o  Commit 3 (HEAD -> main)  <-- Current commit
    |
    o  Commit 2
    |
    o  Commit 1
    

    To save the change, the file needs to be committed:

    git commit -m "Revert <file> to its state in Commit 2"
    

Now the commit history of our repository will look like this:

o  Commit 4 (HEAD -> main)  <-- New commit
|
o  Commit 3
|
o  Commit 2
|
o  Commit 1

Commit 4 contains only the reverted <file> from Commit 2, while the rest of the files remained as they were in Commit 3.

Now you are ready to checkout the equipment.txtfile so that it matches the version in which the swimsuit was not present in the list. You need to tell git which commit to get by giving its ID. Run git log to find the commit message that you know was set to the commit you’re looking for. Then copy its ID (note that your ID will be different from the one in the command below) and use it to checkout the equipment.txt file to that commit.

Careful that you write the name of the file, checkout does something quite different without a specified file name (you would end up in the “detached HEAD state”. Scary, I know.)

git checkout 0ecfb80ba19e5ede972ed3e6dc22c82f2015812c equipment.txt

Git modifies the working directory version of the file to match the specified commit (0ecfb8). If you run git status you will see that equipment.txt is marked as modified and automatically staged. Now the only thing that is left to do is to commit the change.

git commit -m "YOUR COMMIT MESSAGE"

git restore is a command introduced in Git 2.23 that provides a clearer way to undo changes. To archive the same result as above, you would run:

git restore --source=<commit ID> <file>

This command modifies the working directory but does not stage the changes automatically.

Part 3 - Push to GitHub

You want to make sure that all your friends have access to the packing list for the ski trip so you decide to push it to GitHub.

Here is how you do it:

Step 1

Sign in to GitHub and create a new repository. Give it a name, leave all the other options as they are (do not add a README) then click on Create repository.

Step 2

At the top of your newly created repository you should see GitHub’s Quick Setup box. Select the SSH option by clicking on it and copy the SSH address. It looks something like: git@github.com:YOUR_USERNAME/YOUR_REPO_NAME.git

Step 3

Go back to your ski_trip project folder on Vera. Add the remote repo to your local repo.

git remote add origin git@github.com:YOUR_USERNAME/YOUR_REPO_NAME.git

To verify that everything worked run:

git remote -v

You shoud see something like this:

origin git@github.com:YOUR_USERNAME/YOUR_REPO_NAME.git (fetch)
origin git@github.com:YOUR_USERNAME/YOUR_REPO_NAME.git (push)

Step 4

Check the name of the branch you are on.

git branch

This will show master (old default name) or main (new default name). It doesn’t matter which name your branch has (you can always rename it) but make sure you use the correct name in the next command.

git push -u origin master

You have now pushed your local repository to GitHub!

The -u flag stands for --set-upstream. It links your local branch to the remote branch. Git will remember the upstream branch, so in the future, you can simply run git push and git pull.


Summary

git init → create an empty repository.
git status → show the current status of your project.
git add → add the file to the staging area.
git commit -m → create a commit with the staged changes.
git log → show the project’s history.
git diff → display the difference between current status and latest commit.
git checkout → explore and retrieve any committed version of a file.


Extras

The information in this section is just for your own knowledge and understanding of Git. It is good to know that these things exist even though we don’t have the time to cover them in this tutorial.

Undoing all uncommitted changes

The HEADtag refers to the latest commit on the current branch. It represents the current state of the repository. If we run git checkout HEAD equipment.txt we replace the version of the file in our working directory with the version in the latest commit → This command undoes any uncommitted changes to the file, restoring it to its last committed state.

Undoing changes made by a specific commit

In this tutorial we have looked at how to go back to a previous version of a file . You can also perform similar operations to undo all the changes done by a specific commit using git revert <commit ID>. This command is a safe and history-preserving way to undo a specific commit: it creates a new commit that undoes the changes made by the specified commit. Instead of removing the commit from the repository’s history, it reverses the changes made by the specified commit while preserving the repository’s history. This ensures that:

Assume your commit history looks like this:

o  Commit 3 (HEAD -> main)
|
o  Commit 2
|
o  Commit 1

If you run:

git revert <Commit 2>

You’ll get a new commit that reverses the changes made in Commit 2:

o  Revert "Commit 2" (HEAD -> main)
|
o  Commit 3
|
o  Commit 2
|
o  Commit 1

Detached HEAD state

Do not use git checkout <commit ID> without a file name to undo changes that were committed since then. This command allows you to inspect or temporarily work with the state of the repository at a specific commit. However, it moves you to a detached HEAD state, meaning that the HEAD tag is no longer attached to a branch. Instead, it points directly to the specified commit. In this state:

If you just check out a commit, it does not undo changes in the repository’s history. For more details, see the Reset,Checkout, and Revert page under the Further Reading section below.

Further reading


Chalmers University of Technology