Learn Git in 10 Minutes
Tags: programming, git, development
Published: 2023-11-05 23:21:15

---
title: Learn Git in 10 Minutes
published: true
description: It's only going to take us 10 minutes to cover 90% of git's usage.
tags: programming, git, development
---

![Image of Git](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bj0d9bnhqyyr6s4al7cw.jpg)

Every developer needs to learn Git. It's how we version control our code. By using git, we can step through every change we've ever made, forward and backward in time. 

This is crucial when mistakes are made. Instead of having to rewrite everything manually, you can simply revert your changes or hop to an earlier commit. 

It's only going to take us 10 minutes to cover 90% of git's usage.

### Installing Git
First, we need to make sure git is installed on our system.

Windows:
```powershell
# Using winget in a powershell window
winget install git-all

# Chocolatey
chocolatey install git-all
```

MacOS:
```bash
# Using Homebrew
brew install git-all
```

Linux:
```bash
// Ubuntu/Debian
apt install git-all

// Arch
pacman -Sy git-all

// CentOS/Fedora
yum install git-all
```

You can find more info about [installing git here](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).

### Starting a git repo

We'll start by creating a new project. In my case, Ill be starting a new repo for a NES emulator I'll be writing in C. If you dont know where to store your projects, create a `projects` directory wherever you know you'll find it.

Start your own project and name it whatever you'd like.

I'll be naming my project `DrNES` and moving into the directory.

```bash
# Init project
mkdir -p DrNES

# Change dir into DrNES
cd DrNES
```

Now that we have our project directory created and we're inside of it, we can start a git repo.

```bash
# Start a git repo
git init

# Check for .git directory
ls -al .git
```

This makes the project directory we created into a git repo. 

### The Basics of Git

From here, we can create a few files for git to find.

In my case, Im going to create a source `src` folder with `main.c` in it and a `README.md`.

This is going to lay the base file structure for my repo.

```bash
# Create README
touch README.md

# Make src folder
mkdir -p src

# Add main.c to src
touch src/main.c
```

For now these will be empty files.

#### Git Status

If we do a `git status`, we will see what git is currently tracking for changes.

```bash
git status

# Output
On branch main

No commits yet

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

nothing added to commit but untracked files present (use "git add" to track)
```

#### Git Add

In order for git to start tracking these files, we need to use `git add`. This command can be used to add individual files or all files in the directory.

```bash
# Add one file to track
git add README.md

# Add everything in repo to track
# The '.' means to add everything in this directory
git add .

# Output
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   README.md
        new file:   src/main.c
```

In my case, I use `git add .` to make git track everything in my directory.

#### Git Commit

Once we've added our files to track, we need to commit to the changes. We use the `git commit` command to do this.

```bash
# Commit our changes
git commit -m "init commit"

# Output
[main (root-commit) 1b13406] init commit
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md
 create mode 100644 src/main.c
```

Whenever we commit to our changes, we have to add a message to the commit for the `git log`. If we just did `git commit`, it would drop us into vim or whatever other editor you have set as the default.

To bypass being dropped into vim, we use `git commit -m "My message here"`.

#### Git Push

Now we can use `git push` to push our changes to a remote repo.

To that, however, we need a remote repo, otherwise we will get the following error:

```bash
# Push git changes
git push

# Output
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using

    git remote add <name> <url>

and then push using the remote name

    git push <name>
```


#### Setting up a Github

At the moment, we dont have a remote repo to push our changes to.

Thats where something like [Github](https://github.com) or [Gitlab](https://github.com) come in.

These are remote servers that allow us to host and share our code with the world, provided by those two companies.

For my repo, Ill be using Github. I already have an account, but it should be simple to sign up for one.

Once you do, navigate to the "Repositories" tab and click "New" in top right hand corner.


![Create a new repo photo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d76b9jcyv6i01e3l8tsh.png)


That will take you to a "Create new repository" page.

![Options to fill out for creating new repo on Github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2gt5huov67en9bhr704.png)

On this page, we want to:

- Give the repo a name
- Add a description
- Set repo to public or private (your choice)
- Click "Create repository"

We do *not* want to initialize the repo with a README, because we already have a README. As of right now, I dont want to add a `.gitignore` or license. I want this repo to be blank.

If we didnt already have a repo to push to Github, I would have added the README, added `.gitignore`, and selected a license.

After we've created our Github repo, its going to ask whether we want to "create a new repo" or "push an existing one".

We're doing the latter, so we will follow those directions.

![Pushing an existing repo to Github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4oomjt715svp0x3vg5x1.png)

We do this in our terminal where our project repo is. 

Lets look at each command:

- `git remote add origin github.com/User/myrepo.git` tells our local git repo where to find our remote git repo.
- `git branch -M main` creates a main branch in our local repo. This main branch should be protected, more on that later. 
- `git push -u origin main` allows us to push our changes to the upstream repo main branch `-u origin main`

Our `git push` may error out.

This is because we have to define an authentication method with Github.

We have two options:

- [Use the Github CLI to authenticate](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#ssh)
- [Create an SSH key and add it to Github](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)

Once we have that situated, we can try our `git push` again.

```bash
# Push changes to Github
git push -u origin main

# Output
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 10 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (4/4), 301 bytes | 301.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/0xGlitchbyte/DrNES.git
 * [new branch]      master -> master
branch 'master' set up to track 'origin/master'.
```

If we go back to Github, we should see something like this:

![What the repo looks like after being pushed to Github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4l2thbp2li4fi7l90xcx.png)

That's how we know our repo has been successfully pushed.

#### Best Practices for Git

Now that we have successfully added, committed, and pushed changes to Github, we want to start developing.

Remember I said we want to protect `main`?

Best practice is to develop on a separate branch besides `main` so we dont push changes that will mess up the `main` branch.

So we will create a `dev` branch.

```bash
# Create dev branch
git branch dev

# Switch to dev branch
git switch dev

# Push changes from local dev to remote dev
git push -u origin dev

# Output
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 10 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 410 bytes | 410.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'dev' on GitHub by visiting:
remote:      https://github.com/0xGlitchbyte/DrNES/pull/new/dev
remote:
To https://github.com/0xGlitchbyte/DrNES.git
 * [new branch]      dev -> dev
branch 'dev' set up to track 'origin/dev'.
```

Now when we `git add` and `git commit` on this branch, it wont affect our main branch.

Since main is our source of truth branch, where all production ready code gets push to, we need to do a [pull request in Github](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) to merge `dev` into `main`.

Once all changes have been approved and the pull request has been merged into `main`, other people can use `git pull` to get the latest changes.

You can also setup a `.gitignore` file in your directory. This file will allow you to exclude files and file types to be excluded from being added for staging commits.

#### Different Git commands to be aware of
#### Git Clone

If you find a repo you come across that you'd like to contribute to, you can use `git clone` to pull it from a remote server (i.e. Github) to your local machine.

```bash
# Cloning the DrNES repo with HTTPS
git clone https://github.com/0xGlitchbyte/DrNES.git

# Cloning with SSH and changing the folder name
git clone git@github.com:0xGlitchbyte/DrNES.git dr_nes
```

#### Git Fetch

`git fetch` updates your remote-tracking branches under `refs/remotes/<remote>/`. This operation is safe to run at any time since it never changes any of your local branches under `refs/heads`. This is used instead of `pull` when you just want to update the remote references.

```bash
git fetch 
```

#### Git Remove

`git rm` will remove files from your git repo and filesystem, if you specify it.

```bash
# Remove files from cache
git rm --cache
```

#### Git Log

`git log` allows us to see a log of our commits. This is useful when we'd like to view changes passed commits may have done, or to switch to a different commit.

```bash
git log

# Output
commit 124d9e29ac5ddac77c911c83c2100ca54f9d04d0 (HEAD -> dev, origin/dev)
Author: 0xGlitchbyte <49317853+0xGlitchbyte@users.noreply.github.com>
Date:   Sun Nov 5 15:40:47 2023 -0500

    added hello world

commit 1b134069e7dd4469b3439b02b82b2a0d9db4e535 (origin/master, master)
Author: 0xGlitchbyte <49317853+0xGlitchbyte@users.noreply.github.com>
Date:   Sun Nov 5 14:22:22 2023 -0500

    init commit
```

#### Git Show 

`git show` shows us the details and metadata of our last commit

```bash
git show

# Output
commit 124d9e29ac5ddac77c911c83c2100ca54f9d04d0 (HEAD -> dev, origin/dev)
Author: 0xGlitchbyte <49317853+0xGlitchbyte@users.noreply.github.com>
Date:   Sun Nov 5 15:40:47 2023 -0500

    added hello world

diff --git a/src/main.c b/src/main.c
index e69de29..18e3a28 100644
--- a/src/main.c
+++ b/src/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main() {
+  printf("Hello World!");
+  return 0;
+}
(END)
```

#### Git Diff

`git diff` allows us to view the difference between two commits.

```bash
# Will compare last commit to current changes
git diff

# Output
diff --git a/src/main.c b/src/main.c
index 18e3a28..139eeca 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,9 @@
 #include <stdio.h>

 int main() {
+  // I have added some comments here
   printf("Hello World!");
+
+  // And here!
   return 0;
 }
(END)
```

#### Git Stash

`git stash` allows us to stash away any changes we have made in our current branch. This is useful when we want to keep our changes, but go back to a clean working directory to try something else.

```bash
git stash

# Output
Saved working directory and index state WIP on dev: 124d9e2 added hello world
```

#### Git Reset

`git reset` will reset our changes back to a clean working directory without saving them.

```bash
git reset
```

#### Git Branch

`git branch` will show a list of all current branches in the git repo.

```bash
git branch

# Output
* dev
  master
(END)
```

#### Git Merge

`git merge` allows you to join two development histories together. You use `git merge` when you want to reconcile other branches into `main`, for example. When you merge histories, its important to note you will have to reconcile any conflicting differences between the two. 

```bash
# Merge dev into master with a message
git merge -m "My message here" dev
```

#### Git Rebase

`git rebase` allows you to easily change a series of commits, modifying the history of your repository. You can reorder, edit, or squash commits together. You may not want to merge back into `main` just yet, so you can pull a version, rebase, and continue development from the point you rebased.

```bash
git switch dev
git rebase main
```

#### Git Restore

`git restore` allows you to restore or discard unstaged files in your git repo.

```bash
# Restore a file
git restore filename.txt
```

#### Git -h

`git -h` is shorthand for `git --help`. It will list all the options you can use with git. `man git` will give you the manual page on linux for git.

```bash
git -h

usage: git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [--super-prefix=<path>] [--config-env=<name>=<envvar>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone     Clone a repository into a new directory
   init      Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add       Add file contents to the index
   mv        Move or rename a file, a directory, or a symlink
   restore   Restore working tree files
   rm        Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect    Use binary search to find the commit that introduced a bug
   diff      Show changes between commits, commit and working tree, etc
   grep      Print lines matching a pattern
   log       Show commit logs
   show      Show various types of objects
   status    Show the working tree status

grow, mark and tweak your common history
   branch    List, create, or delete branches
   commit    Record changes to the repository
   merge     Join two or more development histories together
   rebase    Reapply commits on top of another base tip
   reset     Reset current HEAD to the specified state
   switch    Switch branches
   tag       Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch     Download objects and refs from another repository
   pull      Fetch from and integrate with another repository or a local branch
   push      Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
```

---

### Final Thoughts

Git is an important tool to learn, but its not difficult to learn.

The majority of the time, youll be using these commands:

- `git add`
- `git commit -m `
- `git push`
- `git pull`
- `git clone`

The rest are good to learn, but will be used on a case by case basis.

You can use git on any files you'd like to version control, from code to text documents.

The more you practice, the better youll get at it.