# Git Commands & GitHub

## 1. What is Git?

**Git** is a **distributed version-control system** for tracking changes in any set of files, originally designed for coordinating work among programmers cooperating on source code during software development. Its goals include speed, data integrity, and support for distributed, non-linear workflows. - [Wikipedia](https://wiki2.org/en/Git)

Simply put, Git helps users for tracking different versions of the software and easily can be reverted back between versions in case of unexpected results - instead of creating multiple copies of the files (for each version) multiple times and renaming them.

**Git** is the *distributed version-control system* whereas **GitHub** is a *repository hosting service*. You need to install Git to use on your computer and it doesn't require internet connection unlike GitHub in which you own / share repositories on the web to work on your projects.&#x20;

![Data flows and Storage levels in the Git revision control system](https://3103118091-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MIz0OFv38fltGbkymGC%2F-MRvniFe4-37ePqKAaJ8%2F-MRvoZ8dBBxEs1ls_fTu%2FGit-operations.png?alt=media\&token=71a89815-ed4e-4800-bf38-0fca82c00af1)

### 1.1. Installing & Updating Git

There are multiple options to install Git to your computer. First, open a terminal and check if Git is installed already and if so find the version of Git typing the command below:

```bash
# check git version
>>> git version
git version 2.28.0 # 2nd major, 28th minor and 0th patch version
```

Since it is already install in my local computer, the command prints the version of current git install.&#x20;

If Git is already installed, you can download the latest development version via Git by cloning the git [repository](https://github.com/git/git) or simply upgrade using brew (in MacOS in my case).

```bash
# clone the latest repo
>>> git clone https://github.com/git/git

# or upgrade the version
>>> brew upgrade git
```

If it is your first time, you can download your preferred version of Git from [here](https://git-scm.com/downloads) and install it using the package installer. Follow the link for other options to install Git. Before moving to next section, please make sure you have a good understanding of basic linux commands. If you don't have an experience with linux, please read [Linux | Shell Basics ](https://salihkilicli.gitbook.io/notes/tutorials/git/lbasic)section under the [Version Control](https://salihkilicli.gitbook.io/notes/tutorials/git).

### 1.1. Creating a new Git repository

Use `git init` command to initialize a new repository while you are in a folder that you desire to locate your repo. In order to make sure you are in the correct folder, you can first use `pwd` command to print your working directory, then using `cd dir_path` you can choose the folder you want to create the repo by feeding **relative** or **absolute path** of the desired directory, or create a new directory using `mkdir dir_name` after locating the desired path.

After locating the directory path, use `git init` to create an empty repository, which is ready to upload files. After you typed to command there will be a new hidden file called `.git`. Let's assume you have a new computer with no files in it, and your user name is **username**. A brand new computer (in my case it is a Macbook) usually comes with the folders below:&#x20;

```bash
# print working directory
>>> pwd
/Users/username

# list files inside the directory
>>> ls
Applications        Downloads         Music  
Desktop             Library           Pictures                      
Documents           Movies            Public 

# change directory to Desktop folder
>>> cd Desktop

# list files inside the Desktop folder
>>> ls
```

Since we don't have any files yet, there is no output. Now, let's create a folder called GitHub and initialize our first repo inside that directory after changing directory to that folder.

```bash
# create a new directory called GitHub
>>> mkdir GitHub

# list files inside the Desktop folder (now we have GitHub folder!)
>>> ls
GitHub

# change directory to GitHub
>>> cd GitHub

# initialize your first repo. Congratulations!
>>> init git
Initialized empty Git repository in /Users/username/Desktop/GitHub/.git/

# notice files starting with . are hidden
>>> ls 

# to list hidden files use -a (list all) flag
>>> ls -a
.git

# Type open to display the current folder (start/explorer on Windows)
>>> open .
```

Now, you will be prompted to a new folder which is the current folder. However, there is no files yet. In order to show hidden files press `Shift + Command + .` keys on Mac, or one can let hidden folders be visible from **view options**. Now you can see the files inside the .git folder. We can also view contents of that folder using terminal.

```bash
# change directory to .git folder
>>> cd .git

# list the contents of the .git folder
>>> ls -a
brances            HEAD            objects
config             hooks           refs
description        info
```

Below is a list of top git commands used with necessary `<must>` and optional `[opt]` commands.

| Git Command                                           | Action                                                                                                                                                                                                                                                                                        |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `git init`                                            | Initializes a new Git repository                                                                                                                                                                                                                                                              |
| `git clone <repo>`                                    | Clones an existing repository to your local machine                                                                                                                                                                                                                                           |
| `git status`                                          | Displays the status of the working directory and staging area                                                                                                                                                                                                                                 |
| `git add <file>`                                      | Adds specified files to the staging area                                                                                                                                                                                                                                                      |
| `git add [. -a]`                                      | <p><code>.</code> option adds all changed files in the current directory to the staging area. <br><br> <code>-a</code> or <code>--all</code> option adds all the files to staging area regardless of their relative path.</p>                                                                 |
| `git commit [-a] -m "msg"`                            | <p>\[Adds] Commits changes in the staging area with a provided commit message<br></p><p><code>-a</code> or <code>--all</code> option automatically stages files that have been modified and deleted. It does <em>not</em> stage new, untracked files.</p>                                     |
| `git push`                                            | Pushes committed changes to a remote repository                                                                                                                                                                                                                                               |
| `git pull`                                            | Fetches and integrates changes from a remote repository into the current branch                                                                                                                                                                                                               |
| `git fetch`                                           | Downloads objects and refs from another repository without merging                                                                                                                                                                                                                            |
| `git branch`                                          | Lists existing branches, and creates or deletes branches                                                                                                                                                                                                                                      |
| `git branch -b <branch>`                              | Creates a new branch with the specified name                                                                                                                                                                                                                                                  |
| `git branch -m <old_name> <new_name>`                 | Renames branch `old_name` to `new_name`                                                                                                                                                                                                                                                       |
| `git cat-file -p <hash>`                              | Displays the contents of a commit given by the hash.                                                                                                                                                                                                                                          |
| `git checkout <branch>`                               | Switches to the specified branch                                                                                                                                                                                                                                                              |
| `git checkout <file>`                                 | Restores a specific file from the current HEAD or a specified branch                                                                                                                                                                                                                          |
| `git config --action --scope <section.key> <"value">` | <p>Edits / lists global / local git configuration file.<br><br>Actions: <code>add</code> <code>edit</code> <code>get</code> <code>set</code> <code>unset</code> <code>list</code>, etc.<br>Scopes: <code>global</code> <code>local</code> <code>system</code> <code>worktree</code>, etc.</p> |
| `git merge <branch>`                                  | Merges the specified branch into the current branch                                                                                                                                                                                                                                           |
| `git diff`                                            | Shows changes between commits, commit and working tree, etc.                                                                                                                                                                                                                                  |
| `git [--no-pager] log [-n N]`                         | Displays a list of commits on the current branch. Use `-n N` to show top N lines.                                                                                                                                                                                                             |
| `git remote -v`                                       | Shows existing remotes with URLs                                                                                                                                                                                                                                                              |
| `git remote add <name> <url>`                         | Adds a new remote repository under a specified name                                                                                                                                                                                                                                           |
| `git stash`                                           | Temporarily saves changes in the working directory that are not ready to be committed                                                                                                                                                                                                         |
| `git stash apply`                                     | Applies stashed changes back into the working directory                                                                                                                                                                                                                                       |
| `git rebase <branch>`                                 | Reapplies commits from the current branch onto the specified base branch                                                                                                                                                                                                                      |
| `git reset <file>`                                    | Removes specified files from the staging area                                                                                                                                                                                                                                                 |
| `git reset --hard`                                    | Resets the index and working directory to the last commit, discarding all changes                                                                                                                                                                                                             |
