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
:
Ubuntu
Git can be installed from the official Ubuntu package repository via apt
:
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.
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 valuemain
. - You may want to set the setting
core.editor
to use your preferred editor. I usenvim
, but most users may findnano
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.
This will create a hidden directory /tmp/my-first-repo/.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:
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:
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.