# Git

## What is Git?

* Git is a popular open-source version control tool commonly used for code but can be used with all types of files
* More information about Git can be found on its [website](https://git-scm.com/)

## Install

* Git is typically installed by default on Linux distributions and MacOS however it will need to be installed on Windows
  * [Git Download](https://git-scm.com/downloads)
  * Windows: `winget install git.git`
  * Linux: `sudo apt install git`
  * MacOS: `brew install git`

## Pushing Local Code to a Remote Repository

* With an empty remote repository, we can add local code to it

{% code overflow="wrap" fullWidth="false" %}

```bash
# set the origin to the remote repo
git remote add origin <repoUrl>

# push local code to the remote main branch
git push -u origin main
```

{% endcode %}

## Cloning Repositories Locally

* We can download a repository locally if we have permission

{% code overflow="wrap" %}

```bash
# via HTTPS
git clone <URL> 

# via SSH
git clone <sshLink>
```

{% endcode %}

## Merging Code

* When you want to merge your changes to a repo
* GitLab - Merge Request (MR)&#x20;
* GitHub - Pull Request (PR)

## Merge Conflicts

* This can occur during a merge when your file is different than an existing file and git is unable to determine which changes should be committed.
* The error may look like this after running `git push origin <branchName>`

{% code overflow="wrap" %}

```bash
! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'http://gitlab.com/tyler/myproject.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

{% endcode %}

* To fix, run `git pull origin <branchName>` (the conflicting branch) and identify the problem file(s) in the output.

```bash
[snip]
CONFLICT (add/add): Merge conflict in file.txt
Auto-merging file.txt
Automatic merge failed; fix conflicts and then commit the result.
```

* Open the file (GUI, IDE, etc.) and select the data to keep removing all the git added stuff and leaving only the data you want.

```bash
# file.txt

<<<<<<< HEAD # your changes
My changes are here!
=======
The data in the branch!
>>>>>>> 2lk3lm23lrl2k3ml2m3l2n3ln2l3lsdkglsadg # the commit hash on the remote branch
```

```bash
# file.txt

My changes are here!
```

## Fork

* Someone with READ access can download your repo/code, make changes, and then open a Merge Request for you to approve

## Rebasing

* When the branch you're working on is behind commits from others&#x20;

### Merging

* Running this command from your branch brings changes from others into your branch and keeps the git commit history intact

```bash
git merge main
```

### Rebasing

* Running this command moves your branch on top of the updated branch, changing the git commit hashes from others.&#x20;
* Not a big deal but your coworkers may not like this due to the commit history changing

```bash
git rebase main
```

### Squashing Commits

* When you have multiple commits and want to squash them into one
* The final commit will be `Addng new feature`

```bash
# view commit history
git log

# squash the last 3 commits into one
git rebase -i HEAD~3

# replace `pick` with `squash`
pick 3h3ih Adding new feature
squash 4j69j Fixing typo
squash 6k49g Adding change
```

* If you've already deployed a commit to a remote branch, but now need to revert it or change it, here's how you can squash them,

{% code overflow="wrap" %}

```bash
# view commit history
git log
commit ljsdflhsd3o2h8hd
Author: <author>
Date: <date>

    <latest commit message>
    
commit 9sdfh98sh9f839hh3
Author: <author>
Date: <date>

    <previous commit message>
```

{% endcode %}

* Let's say you want to squash the new changes into the old commit

```
# select last two commits
git rebase -i HEAD~2

# merge remote branch into yours
git pull 

# push latest commit to remote branch
git push
```

## Cherry Picking

* When you want to incorporate a particular commit from another branch into your branch

```bash
git cherry-pick <commitHash>
```

## Reverting Commits

* You've committed some changes and now want to undo them

### Keeping Commit History&#x20;

* Removing the commit shows the file(s) as deleted in the commit history

```bash
git revert <commitHash>
```

### Undoing Commit

* This undoes your commit
* Use `--soft` to undo the commit but keep your modified file(s)
* Use `--hard` to undo the commit and delete your modified file(s)

```bash
# remove last commit ~1
git reset --soft HEAD~1
git status

    On branch featureA
    Changes to be committed:
        added:    file.txt
    

# remove last commit ~1
git reset --hard HEAD~1
git status

    On branch featureA
    Nothing to commit
```

## Stashing

* Storing your code when you don't want to commit it yet but need to hop to another branch and don't want your modified code to come with you

```bash
# stash code
git stash

# list code kept in stash
git stash list

    stash@{0}: WIP on main: added new feature X (1 hour ago)
    stash@{1}: Bugfix for issue#123 (2 days ago)
    stash@{2}: Update README.md (yesterday)


# show contents of stash
git stash show stash@{0}

    diff --git a/new_feature.py b/new_feature.py
    new file
    +++ b/new_feature.py
    

# remove stashed item
git stash pop stash@{1}
```

## Reflog

* Shows the state of the repository and enables you to undo mistakes e.g., you deleted a file

```bash
# show changes
git reflog

    34o4on43mf0sd  HEAD@{0}: checkout: moving from main to feature (HEAD@{0})
    has34o4omf0sd  HEAD@{1}: commit: added feature X (2 hours ago)
    64osafdamf0sd  HEAD@{2}: commit: initial commit (yesterday)
    78o4sdsdh330s  ORIG_HEAD@{0}: commit: initial commit (yesterday)
    

# undo a change
git reset --hard <commitHash>
```

## Useful Commands

### General

```bash
# get help
git --help
man git

# download/clone repo
git clone <repositoryLink>

# view changes made since last commit or initial download 
git status

# queue files for commit
git add <fileName>
git add *

# commit files
git commit -m "description of change"

# push files to branch
git push
git push -u origin <branchName>
git push --set-upstream origin <branchName> 

# view git log
git log
git log -p <commitHash>

# checkout a commit
git checkout <commitHash>
```

### Branches

```bash
# view all local branches
git branch

# view all remote branches
git branch -r

# view all local and remote branches
git branch -a

# create new branch and switch to it
git checkout -b <newBranchName>

# switch branch
git branch <branchName>

# rename branch
git branch -m <oldBranchName> <newBranchName>
```

## Modify Terminal to show current git branch

* Update your shell's configuration file e.g., `~/.zshrc` or `~/.bashrc`
* Save and then reload your shell for the changes to take effect `source ~/.zshrc`

```sh
parse_git_branch() {
    git branch 2> /dev/null | sed -n -e 's/^\* \(.*\)/[\1]/p'
}
# color #s found here: https://misc.flogisoft.com/bash/tip_colors_and_formatting
COLOR_DEF='%f'
COLOR_USR='%F{243}'
COLOR_DIR='%F{197}'
COLOR_GIT='%F{39}'
NEWLINE=$'\n'
setopt PROMPT_SUBST
export PROMPT='${COLOR_USR}%n@%M ${COLOR_DIR}%d ${COLOR_GIT}$(parse_git_branch)${COLOR_DEF}${NEWLINE}%% '
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.techwithtyler.dev/coding-and-cli-tooling/cli-tools/git.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
