> For the complete documentation index, see [llms.txt](https://mamawhocode.gitbook.io/devops/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mamawhocode.gitbook.io/devops/fundamentals/git.md).

# GIT

### What is Git?

Git is a `distributed` version control system. Every developer maintains a local copy of the main repository and edits and commits to the local copy.

### Git workflow

<figure><img src="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd47de46b-2c7b-43d2-8a9a-a2ebb7600347_1324x2004.jpeg" alt=""><figcaption><p>Distributed version control</p></figcaption></figure>

### Basic commands

<details>

<summary>Configuration</summary>

```bash
# list all configurations
git config --list

# config user name & email
git config user.email phuong@example.com
git config user.name phuong
```

</details>

<details>

<summary>Clone &#x26; Remote</summary>

```bash
# clone a repo to local machine
git clone https://github.com/phuongnht/myapp.git

# remote to multiple remote repo
# git remote add [name] [url]
git remote add github https://github.com/phuongnht/myapp.git

# list all your remote repos
git remote -v

# if specified a name, when push using -u flag
# git push -u [name] [branch]
git push -u github master
```

</details>

<details>

<summary>Branch</summary>

#### What is branch?

`Pointer` to specific commit in your working repo.

`Master` is the default branch in a git repo.

```bash
# create new branch
git checkout -b <new branch name>
# or, but you need to use git checkout to switch to that new branch
git branch <new branch name>
git checkout <your new branch>

# list the branches
git branch

# to view branch both local & remote, using -a
# the remote branch have prefix: remotes
git branch -a
sarah (master)$ git branch -a
* master
  story/frogs-and-ox
  remotes/origin/master
  
# delete a branch
git branch -d <branch name>
```

#### Rename branch

```sh
# rename a branch
git branch -m <new name>

# push new branch name
git push origin -u <new name>

# delete remote branch
git push origin --delete <old>
```

</details>

<details>

<summary>Log</summary>

```sh
# list changed file with git log
git log --name-only

# display the logs in compact way (1 log per line)
git log --oneline

# list only 3 latest commits alone
git log -3

# view log as graph
git log --graph --decorate
```

</details>

<details>

<summary>Revert &#x26; Reset</summary>

#### Revert

```bash
# undo the last commit
git revert HEAD
```

#### Reset

* \--soft: keep the history
* \--hard: so embarrased to keep the historycod

#### Reflog (undo --hard reset)

```bash
# show all reflog
git reflog

# reset the --hard reset, the hashvalue is where 
# the HEAD point to before the reset
git reset --hard <hashvalue>
```

</details>

### Merge

#### Fast-Forward and No-FF

There are 2 types of merge in GIT

| Feature          | Fast-Forward Merge            | No-Fast-Forward Merge             |
| ---------------- | ----------------------------- | --------------------------------- |
| Merge type       | Simple, Fast                  | Complex, require merge commit     |
| Branch history   | Linear, no commit             | Non-Linear, new merge commits     |
| Merging strategy | used when changes are in SYNC | used when changes have Diverged   |
| Command          | `git merge <branchname>`      | git merge `--no-ff` \<branchname> |

#### Rebasing

#### Cherry pick

* **Use case**: when you do not want to merge all the changes from another branch (rebasing), and only want to pick 1 commit from another branch.

### Special file in Git

{% tabs %}
{% tab title=".gitignore" %}

{% endtab %}

{% tab title=".gitkeep" %}

{% endtab %}
{% endtabs %}

### Best practices

* Keep your commit atomic (1 commit solve 1 issue)

### Resources

{% embed url="<https://quickref.me/git>" %}
