31
All you need to know to survive in Git!
* Photo by milan degraeve on Unsplash
Learning Git can be really overwhelming. There are a lot of new concepts to learn and there are a lot of commands that you need to memorize. Every time you think you know what you are doing, Git throws a new challenge at you and makes you humble.
Of course when you are a Git beginner this happens more often. It can be demotivating and frustrating.
I am here to tell you that you don't need to beat yourself up about it. Even seasoned Git users need to look up commands now and then.
In the beginning you just need to survive. You need to know just enough Git to get by. Just enough so that it gets out of your way, and lets you focus on other activities like coding, building, shipping, etc.
You need some basic Git survival skills!
To survive, there are a subset of Git concepts that you need to understand, and a handful of commands to remember:
Git repositories are not magic. They are just a folder of files with a .git
folder inside. Go ahead and list all the files (and hidden files) in a Git repository. You will see a .git
folder in there. In that folder, Git keeps a record of the commits that have been made, who made them, when, and so on.
When you initialize a repository using git init
inside a folder, you create the .git
folder there for the first time. From then on, Git will track everything that happens in your repository.
When you clone a repository, you are basically downloading a folder that includes the project files but also a .git
folder. Git will set up things so that you can communicate with where you cloned from (for example GitHub) so that later you can send your changes to it (push) or update from it (pull). To clone a repository you need to provide the URL for that repository:
$ git clone [URL]
You should be able to get an overview of your local changes in Git at any time. This is useful just before you commit or if you just want to remember what files you have changed. You can easily do that using the status command in your repository:
$ git status
On branch feature_1
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: file.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
file2.txt
no changes added to commit (use "git add" and/or "git commit -a")
Here you can see that we are inside a branch called feature_1
. We have modified a file called file.txt
and there is a new file (file2.txt
) that is not added to Git yet and therefore it is reported as "Untracked".
Now if you want to know what are the changes in file.txt
, you can use the diff command like this:
$ git diff file.txt
diff --git a/file.txt b/file.txt
index be05e9c..163b853 100644
--- a/file.txt
+++ b/file.txt
@@ -1,3 +1,3 @@
Something
Something more
-
+Something else
Now that's a bit cryptic. I personally don't like it. To get an easy-to-understand diff, I suggest you use the Git integration in your favorite text editor or IDE. Here is an excellent article describing how to set up VSCode so that it opens from terminal and shows you a good-looking diff.
The difference between the two, and the fact that there are two steps to committing, is sometimes confusing for Git beginners. I wrote an article about what the differences are and how you can use staging and committing to your advantage. Give it a read.
Another thing you need is the ability to find things in the repository history. Git history is basically a log of all the things that has happened in the repository.
Most Git GUIs (and Git integrations in text editors and IDEs) offer a visual and intuitive presentation of this log in a form of a tree. You can see the branches, commits, tags, changed files, diffs, etc.
Although you can definitely investigate the Git history in a terminal using the commands below, a Git GUI offers a more
intuitive experience when it comes to investigating the history. I usually recommend learning Git in a terminal first before going to GUIs,
but from this particular aspect, GUIs are better.
If you choose to remain in the terminal, the git log
command is your friend. Although the default output is not so helpful, you can create a good-looking visualization of the log using some additional command arguments. You can even create an alias, so you don't need to write those command arguments each time. Read this article to learn how to do it.
You can show the contents of any commit using the commit hash. That's the crazy (but unique) number in front of each commit.
$ git show <commit-hash>
Or you can jump to that commit by checking it out:
$ git checkout <commit-hash>
Don't get scared by the somewhat morbid message from git about a detached HEAD. You can switch back to where you were before, using git switch -
.
Branches are one of the most useful concepts in Git. Let's say you want to experiment on your code, for example refactor something or introduce a new feature. You would typically do this in a branch. That way you don't touch the code that already works. When you are satisfied with your results, you can merge your experiment branch to the main branch.
You can create a new branch with:
$ git branch [branch-name]
You can move to another branch using:
$ git checkout [branch-name]
You also need to learn how to merge branches. Merging often seems scary to beginners because they are afraid they will write over other people's work or that they will get
a merge conflict.
To prevent writing over other people's work, always make sure that the branch you are merging into is updated. Check out the destination branch and do a pull before you merge:
$ git pull
Already up to date.
$ git merge [your-branch-name]
Sometimes you end up in a merge conflict state. It's just the reality of working with Git. There is no need to panic.
Just follow this guide, and you will become a Git conflict resolution guru.
Sooner or later you will need to put your project on GitHub (or GitLab, or BitBucket, etc). Or you might need to collaborate with others on the same repository.
So you need to send your changes to a remote repository, and download changes from it. This is when push, pull and fetch come into the picture.
Push is pretty obvious. git push
simply sends commits you have done locally in your current branch up to the remote repository. However, if this is the first time you are
pushing a new branch to remote, you need to use a slightly different command:
$ git push -u origin my_new_branch
Remember, this is done only if you have just created my_new_branch
and this is the first time you are pushing it to the remote repository. Read more about this here.
Before we get to pull, we need to talk about fetch. git fetch
asks the remote about the latest developments. It doesn't change your files. It just downloads the history from remote so that you can visualize what has happened on the remote since the last time you synced.
Pull is like fetch except that it will not only update history, it will also merge the changes from remote to your local files. If you have changed some file and
another colleague has changed the same file and pushed it, you will get a merge conflict on that file if you do a pull. This is not bad. It's just Git asking you for guidance on how to merge these changes. You can follow my merge conflict resolution guide to resolve it.
One important rule is to always do a pull before you push your changes. This way if there is a conflict, you get a chance to solve it locally and do not risk overwriting other people's work.
Now you are equipped with all the survival skills you need to use Git on a day-to-day basis. My guess is that this list helps you in about 90% of your work with Git.
There are of course more things to learn. For example, when you are comfortable with these basic concepts, you might want to take a look at rebasing and cherry-picking.
You don't need them right now, but they might come in handy one day.
So to recap, you need to know how to:
- initialize and clone a repository,
- check the status of your work,
- stage and commit your changes,
- check the history of the repository,
- make branches and jump between them,
- merge branches and resolve merge conflicts,
- sync with a remote using push and pull.
To help you remember all these commands, I have created a cheat sheet that you download. Print it out and put it somewhere that is easy to see.