Skip to content

Using Git

Now that you know what Git is, let's ensure that it's installed, and look at some basic commands.

Note: Git is cross-platform, so a lot of this chapter will work similarly on Linux, and also on other platforms. If you are on Windows, certain paths (e.g. /tmp/) may not be applicable, so use something more appropriate. Naturally, installation on Windows systems will not be covered.

Installing Git

Arch Linux

Git can be installed from the official Arch Linux package repository via pacman:

$ sudo pacman -S git

Ubuntu

Git can be installed from the official Ubuntu package repository via apt:

$ sudo apt install git

Git commands

Git commands are usually called by passing a command argument to git, like in the following examples:

  • git init
  • git pull
  • git clone
  • etc.

Many of those commands take extra arguments, as we will see shortly.

Git man pages

Most git commands have their own man pages, which can be accessed via man. To access the man pages for a particular command, you typically add a dash and the name of the command. Based on our previous examples, the respective man pages can be accessed with the following commands:

  • man git-init
  • man git-pull
  • man git-clone
  • etc.

Configuring Git

Before we start using Git, we need to configure a few settings. At the very least, we need to enter our name, and email address. Those will be used to assign an author to every commit.

We can configure Git with the git config command. Replace the text in quotes with your preferred values.

$ git config --global user.name "Your Name"
$ git config --global user.email "your@email"

By default, Git stores configuration options in .git/config inside the Git repository. As your name and email is likely to be the same across different projects, we use the --global option to store them in the global configuration, which is shared across all repositories.

You can list the current configuration by running git config --list (or -l).

You can see some of the available configuration options in the man page available as man git-config.

Tips

  • Depending on your Git version, you may need to set the setting init.defaultBranch to the value main.
  • You may want to set the setting core.editor to use your preferred editor. I use nvim, but most users may find nano simpler. Make sure the corresponding package is installed.

Creating a new repository

If you are starting a new project, you'll want to create a new repository to keep track of your changes. This can be done with git init.

For now, let's just focus on learning Git itself, so we can create some throwaway projects in the temporary directory.

$ mkdir -p /tmp/my-first-repo
$ cd /tmp/my-first-repo
$ git init --initial-branch=main .

This will create a hidden directory /tmp/my-first-repo/.git/.

$ ls -a
./  ../  .git/

Note that I passed the optional location argument . explicitly to initialize the repository in the current directory. You could also do this via the following method, which is equivalent:

$ cd /tmp/
$ git init --initial-branch=main my-first-repo
$ cd my-first-repo

Checking the repo status

As we haven't done anything in this directory yet, the status will be clean. Let's check it now.

$ git status
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Adding files

Let's create a new file, check the status again, add it, and see what happens.

$ echo hell world > hello.md
$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        hello.md

nothing added to commit but untracked files present (use "git add" to track)
$ git add -v .
add 'hello.md'
$ git status

Now, instead of "Untracked files" we can see the file hello.md listed under "Changes to be committed."

Excluding files

Note that there are many files you should not be committing to git.

For Django, this includes:

  • __pycache__ directories containing byte code.
  • node_modules directories when using Django with some JavaScript libraries.
  • The directory containing the virtual environment.
  • The SQLite database.
  • etc.

To exclude files (or directories) from being tracked by git, you can add them to an ignore file. An ignore file can be:

  • A file named .gitignore in the repo root directory.
  • A file named .gitignore in one of the repo subdirectories.
  • A file named ~/.config/git/ignore.

The file should contain a list of patters to ignore, one per line. You can add comments by prefixing them with #. For example:

# Python bytecode
*.pyc
# The virtual environment
.venv/
# The database
db.sqlite3

Any pattern appearing in the root ignore file (the .gitignore file in the repo root) will be ignored throughout the repo. A pattern listed in a subdirectory will be ignored only in that directory and its children.

The ~/config/git/ignore file is a global ignore file, meaning it will be applied to all repositories on that machine.

While global ignore files are very convenient, note that you'll have to ensure any teammates or coworkers do not accidentally commit files that should not be committed.

Creating our first commit

To create a commit, we need to give it a commit message. Let's do that now.

$ git commit -m "initial commit"
[main (root-commit) f92d494] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 hello.md

Tada! Your first commit is done 🎉

Making changes

If you look into our hello.md file, you may notice that we accidentally wrote "hell" instead of "hello." That's not very good, but hey, making mistakes is part of learning. Let's fix our mistake, and see the updated status.

$ sed -i 's/hell /hello /' hello.md
$ git status
On branch main
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:   hello.md
$ git diff hello.md
index 96d2853..3b18e51 100644
--- a/hello.md
+++ b/hello.md
@@ -1 +1 @@
-hell world
+hello world

As git status informs us, we have modified our file. We can review the changes with git diff. If we omit a file name, git diff will show changes across all files. We explicitly checked the changes in our only file by passing it as an argument.

Once we are satisfied with our changes, we can commit them.

$ git commit -a -m "fix: typo in word hello"
[main d586bdc] fix: typo in word hello
 1 file changed, 1 insertion(+), 1 deletion(-)

Seeing history

You can get a list of all commits by running git log. The default output is quite verbose, listing the commit hash, the author, date, and the message of each commit. You can also use --oneline to get a shorter output.

You can also use git blame hello.md to see who made each change line by line.

Branching out

It's common to use branches to work on specific features or fixes. Let's create a new branch to work on. As we will be working on a feature (updating our hello.md file), let's call the branch feat/hello.

$ git branch feat/hello # create a new branch
$ git checkout feat/hello # switch to it
Switched to branch 'feat/hello'
$ git branch # list branches
* feat/hello
  main

We can now make changes in this branch, independently from the main branch. Let's update our file, and commit the changes.

$ echo \nYou will be a Linux expert in no time! >> hello.md
$ git add hello.md
$ git commit -m "feat: complement the reader on their progress"

Our feat/hello branch is now one commit ahead of main.

$  git log --oneline
ee6ee16 (HEAD -> feat/hello) feat: complement the reader on their progress
d586bdc (main) fix: typo in word hello
f92d494 initial commit

We can switch back to our main branch, and update it with the changes we just made. After our changes are merged, we can delete the feat/hello branch.

$ git checkout main
$ git merge feat/hello
Updating d586bdc..ee6ee16
Fast-forward
 hello.md | 2 ++
 1 file changed, 2 insertions(+)
$ git branch -d feat/hello # delete the branch

Recap

Hopefully, this chapter gave you the information you need to start using Git locally. As we live and work in an ever increasingly connected world, in the next chapter we will introduce using Git in the cloud, and collaborating with others.