# Git

## <mark style="color:red;">**Setup & Configuration**</mark>

### <mark style="color:yellow;">**Installing Git**</mark>

#### <mark style="color:purple;">Git is a distributed version control system, to install it (linux-based systems):</mark>

```bash
sudo apt-get install git
```

### <mark style="color:yellow;">**Configuring Git**</mark>

#### <mark style="color:purple;">**Set username and email:**</mark> This sets your identification for every commit.

```bash
git config --global user.name "Your Name"
git config --global user.email "youremail@example.com"
```

#### <mark style="color:purple;">**List all global configurations:**</mark> Shows your git configuration details.

```bash
git config --global --list
```

#### <mark style="color:purple;">**Unset a specific configuration:**</mark> For instance, to remove the globally set username.

```bash
git config --global --unset user.name
```

### <mark style="color:yellow;">**Setting Up Authentication for GitLab**</mark>

#### <mark style="color:purple;">**SSH Authentication:**</mark>

```bash
ssh-keygen -t rsa -b 4096 -C "youremail@example.com"
```

```bash
cat ~/.ssh/id_rsa.pub
```

## <mark style="color:red;">**Repository Operations**</mark>

### <mark style="color:yellow;">**Setting Up GitLab Repository**</mark>

#### <mark style="color:purple;">A step-by-step guide to set up a new project on GitLab:</mark>

1. Login to GitLab.
2. Click on the "+" icon at the top right.
3. Select "New project".

### <mark style="color:yellow;">**Cloning a Repository**</mark>

#### <mark style="color:purple;">Copy a remote repository to your local machine:</mark>

```bash
git clone https://gitlab.com/yourusername/yourrepository.git
```

### <mark style="color:yellow;">**Integrating an Existing Folder with GitLab**</mark>

#### <mark style="color:purple;">Link your local folder with a GitLab repository:</mark>

```bash
cd /path/to/your/folder
git init
git remote add origin git@gitlab.com:yourusername/yourrepository.git
git add .
git commit -m "Initial commit or relevant message"
git push -u origin main
```

## <mark style="color:red;">**Regular Workflow & Common Commands**</mark>

### <mark style="color:yellow;">**Synchronize with Remote Repository**</mark>

#### <mark style="color:purple;">Update your local branch with the latest changes from the remote repository:</mark>

```bash
git pull
```

### <mark style="color:yellow;">**Committing Changes**</mark>

#### <mark style="color:purple;">After making your desired changes, save them to your local repository and then push to the remote repository:</mark>

```bash
git add .
git commit -m "Descriptive commit message"
git push
```

## <mark style="color:red;">**Branch Management**</mark>

### <mark style="color:yellow;">**Creating, Renaming, and Deleting Branches**</mark>

#### <mark style="color:purple;">Handle multiple lines of development within a single repository:</mark>

```bash
git branch new_branch_name
git branch -m old_name new_name
git branch -d branch_name
git push origin --delete branch_name
```

### <mark style="color:yellow;">**Switching Between Branches & Commits**</mark>

#### <mark style="color:purple;">Move between different versions or branches within the repository:</mark>

```bash
git checkout branch_name
git checkout commit_hash
```

### <mark style="color:yellow;">Recovering Lost Files</mark>

#### <mark style="color:purple;">Check Reflog</mark>

```bash
git reflog
```

Identify commit before loss: Look for relevant `HEAD@{n}` entry.

#### <mark style="color:purple;">Create Temporary Branch</mark>

```bash
git branch temp-branch <commit-SHA>
```

#### <mark style="color:purple;">Recover Files</mark>

Checkout temporary branch:

```bash
git checkout temp-branch
```

Files at this state are recoverable. Copy them to a safe location.

#### <mark style="color:purple;">Merge or Cherry-Pick to Current Branch</mark>

Merge:

```bash
git checkout <current-branch>
git merge temp-branch
```

Cherry-Pick:&#x20;

```bash
git cherry-pick <commit-SHA>
```

### <mark style="color:yellow;">Restoring Committed Branches</mark>

If you've accidentally removed a branch in Git, don't worry! You can typically recover it with a few simple steps.

Every action in git is logged.&#x20;

#### <mark style="color:purple;">To find the last commit of the deleted branch:</mark>

```bash
git reflog
```

#### <mark style="color:purple;">For example, you might see an entry like:</mark>

```less
abcdef1 HEAD@{2}: checkout: moving from feature-branch to main
```

{% hint style="info" %}
As an example `abcdef1` is the commit hash.
{% endhint %}

Now that you have the commit hash, you can restore the branch.&#x20;

#### <mark style="color:purple;">Let's assume you want to recover a branch named</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`feature-branch`</mark><mark style="color:purple;">:</mark>

```bash
git checkout -b feature-branch abcdef1
```

## <mark style="color:red;">**Conflict Resolution & Reversion**</mark>

### <mark style="color:yellow;">**Handling Merge Conflicts**</mark>

#### <mark style="color:purple;">When merging or pulling, conflicts may occur. These steps guide you through resolution:</mark>

```bash
git add resolved_file.ext
git commit
```

### <mark style="color:yellow;">Reverting and Resetting Changes</mark>

In Git, you may often find yourself needing to undo changes. Two primary commands to do this are `git revert` and `git reset`. Each serves a different purpose and should be used based on your specific needs.

#### <mark style="color:purple;">git revert</mark>

**Purpose**: The `git revert` command is used to reverse the changes made by a specific commit. It creates a new commit that undoes the changes from a previous commit.

```bash
git revert commit_hash
```

Replace `commit_hash` with the hash of the commit you want to revert.

**Scenario:** Use `git revert` when you need to undo changes but want to keep the history of the original commit. This is a safe method to undo changes in a shared repository because it doesn't alter the project's history.

#### <mark style="color:purple;">git reset</mark>

**Purpose**: The `git reset` command is used to reset the current HEAD to a specified state. It can be used to unstage files, change the current branch's HEAD to a different commit, and even discard changes in your working directory depending on the options used.

```bash
git reset --hard branch_or_commit_name
```

Replace `branch_or_commit_name` with the name of the branch or the hash of the commit you want to reset to.

* `--soft`: Moves the HEAD to a specified commit but keeps your staged changes and working directory.
* `--mixed` (default): Resets the index but not the working tree. Changes are kept but not marked for commit.
* `--hard`: Resets the index and working tree. Any changes to tracked files in the working tree since the specified commit are discarded.

**Scenario:** Use `git reset` when you need to completely undo changes in a local repository. Be cautious with `git reset --hard`, as it can permanently erase changes. It's best used when you have uncommitted changes that you want to discard.

#### <mark style="color:purple;">Understanding HEAD and Its Notation</mark>

In Git, `HEAD` is a reference to the last commit in the currently checked-out branch. It represents the tip of the current branch.

* **Notation**:
  * `HEAD~1`: Refers to the commit before the current one.
  * `HEAD~2`: Refers to two commits before the current one.
  * And so on, where `HEAD~n` refers to the 'n-th' commit before the current HEAD.

#### <mark style="color:purple;">git reset with HEAD Notation</mark>

To undo the last commit, keeping the changes in the working directory:

```bash
git reset --soft HEAD~1
```

To completely remove the last commit:

```bash
git reset --hard HEAD~1
```

**Scenario**: This is particularly useful when you need to undo recent commits in your local repository.

#### <mark style="color:purple;">Best Practices</mark>

* Use `git revert` for public/shared branches to maintain a record of changes.
* Use `git reset` for local or private changes where rewriting history is acceptable.
* Always ensure you have backups of your work before using `git reset --hard`.

## <mark style="color:red;">Merging</mark> <mark style="color:red;"></mark><mark style="color:red;">`dev`</mark> <mark style="color:red;"></mark><mark style="color:red;">into</mark> <mark style="color:red;"></mark><mark style="color:red;">`main`</mark> <mark style="color:red;"></mark><mark style="color:red;">and Resolving Conflicts</mark>

### <mark style="color:yellow;">**Merging Branches**</mark>

#### <mark style="color:purple;">Once you've finished development on the</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`dev`</mark> <mark style="color:purple;"></mark><mark style="color:purple;">branch and it's ready for merging into</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`main`</mark><mark style="color:purple;">:</mark>

```bash
git checkout main
git merge dev
```

### <mark style="color:yellow;">**Identifying and Resolving Conflicts**</mark>

Sometimes, Git can't auto-merge changes and will report a conflict.

#### <mark style="color:purple;">Identify the conflicted files:</mark>

```bash
git status
```

Open the conflicted files in your preferred editor (like VSCode). Conflicts are marked with `<<<<<<< HEAD`, `=======`, and `>>>>>>> branch-name`.

Manually resolve the conflict by choosing which code to retain and which to discard.

#### <mark style="color:purple;">Once you've resolved the conflict in the file:</mark>

```bash
git add conflicted-file-name
```

#### <mark style="color:purple;">After resolving all conflicts, continue the merge process with a commit:</mark>

```bash
git commit -m "Resolved conflicts while merging dev into main"
```

#### <mark style="color:purple;">After successfully merging and resolving conflicts, you'd want to update the remote repository:</mark>

<pre class="language-bash"><code class="lang-bash"><strong>git push origin main
</strong></code></pre>

## <mark style="color:red;">Cleaning Up Local References in VSCode</mark>

VScode sometimes holds onto old branch references that no longer exist on the remote.&#x20;

It's a good practice to prune these references regularly.

### <mark style="color:yellow;">**Pruning Local Branch References**</mark>

#### <mark style="color:purple;">To remove stale branches from your local that no longer exist on the remote:</mark>

```bash
git fetch -p
```

## <mark style="color:red;">**Advanced Operations**</mark>

### <mark style="color:yellow;">**Stashing, Tagging, and Searching**</mark>

#### <mark style="color:purple;">Various advanced operations for better Git management:</mark>

```bash
git stash
git stash apply
git stash drop
git tag v1.0 commit_hash
git log --grep="search_term"
git grep "search_term"
```

### <mark style="color:yellow;">**Viewing Commit History & Using git blame**</mark>

#### <mark style="color:purple;">Examine the modification history of your repository:</mark>

```bash
git log
git log --oneline --graph --all
git blame filename.ext
```

## <mark style="color:red;">**Troubleshooting & Miscellaneous**</mark>

### <mark style="color:yellow;">**Dealing with Authentication Issues**</mark>

#### <mark style="color:purple;">Switch between SSH and HTTPS, or troubleshoot common authentication issues:</mark>

```bash
git remote set-url origin git@gitlab.com:yourusername/yourrepository.git
```

### <mark style="color:yellow;">**Update Default Branch on GitLab**</mark>

#### <mark style="color:purple;">Change the primary branch of your GitLab repository:</mark>

1. Go to your project.
2. Navigate to "Settings" > "Repository".
3. Set the new default branch.

## <mark style="color:red;">**Detailed Commit Inspection**</mark>

### <mark style="color:yellow;">**Show Commit Details**</mark>

#### <mark style="color:purple;">Display changes associated with a specific commit:</mark>

```bash
git show commit_hash
```

### <mark style="color:yellow;">**Reflog**</mark>

#### <mark style="color:purple;">Shows a log of where your HEAD and branch references have been:</mark>

```bash
git reflog
```

## <mark style="color:red;">**Working with Remotes**</mark>

### <mark style="color:yellow;">**List Remote Repositories**</mark>

#### <mark style="color:purple;">Show all remote repositories connected to the local repository:</mark>

```bash
git remote -v
```

### <mark style="color:yellow;">**Add Remote Repository**</mark>

#### <mark style="color:purple;">Connect a new remote repository to the local repository:</mark>

```bash
git remote add remote_name remote_url
```

### <mark style="color:yellow;">**Remove Remote Repository**</mark>

#### <mark style="color:purple;">Remove a connection to a remote repository:</mark>

```bash
git remote remove remote_name
```

### <mark style="color:yellow;">**Fetch from Remote**</mark>

#### <mark style="color:purple;">Download branches and/or tags from another repository, without making any changes to your local branches:</mark>

```bash
git fetch remote_name
```

## <mark style="color:red;">**Patching**</mark>

### <mark style="color:yellow;">**Creating a Patch**</mark>

#### <mark style="color:purple;">Create a patch file of the changes between two commits:</mark>

```bash
git format-patch older_commit_hash^..newer_commit_hash
```

### <mark style="color:yellow;">**Apply a Patch**</mark>

#### <mark style="color:purple;">Apply changes from a patch file to the code:</mark>

```bash
git apply patch_name.patch
```

## <mark style="color:red;">**Rebasing**</mark>

### <mark style="color:yellow;">**Rebase**</mark>

#### <mark style="color:purple;">Apply a series of commits from one branch onto another, effectively re-writing history. Useful for a clean commit history but can be dangerous if not understood well:</mark>

```bash
git rebase branch_name
```

### <mark style="color:yellow;">**Abort Rebase**</mark>

#### <mark style="color:purple;">Stop the rebase process and return to the initial state:</mark>

```bash
git rebase --abort
```

### <mark style="color:yellow;">**Continue Rebase After Conflict Resolution**</mark>

#### <mark style="color:purple;">Continue the rebase process after resolving merge conflicts:</mark>

```bash
git rebase --continue
```

### <mark style="color:yellow;">**Cleaning Up**</mark>

#### <mark style="color:purple;">Remove untracked files from the working directory. This doesn't remove untracked folders or files specified in</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`.gitignore:`</mark>

```bash
git clean -n    # Shows which files would be removed
git clean -f    # Force remove files
```

### <mark style="color:yellow;">**Prune**</mark>

#### <mark style="color:purple;">Remove objects that are no longer pointed to by any commit. This cleans up your local repository:</mark>

```bash
git gc    # Garbage collector
git prune
```

## <mark style="color:red;">**Submodules**</mark>

### <mark style="color:yellow;">**Add a Submodule**</mark>

#### &#x20;<mark style="color:purple;">Add another repository as a submodule in the current repository. Useful when using other projects or shared code:</mark>

```bash
git submodule add repository_url path_to_add_submodule
```

### <mark style="color:yellow;">**Update Submodule**</mark>

#### <mark style="color:purple;">Update the registered submodules:</mark>

```bash
git submodule update --init --recursive
```

### <mark style="color:yellow;">**Bisect**</mark>

#### <mark style="color:purple;">Find by binary search the commit that introduced a bug:</mark>

```bash
git bisect start
git bisect bad                 # Specify the commit where the bug is present
git bisect good commit_hash    # Specify the latest commit where the bug is absent
```

Then, Git will check out a commit in the middle of that range.&#x20;

Test the code, and then mark that commit as `good` or `bad`.&#x20;

Repeat the process until the culprit commit is found. Finally:

```bash
git bisect reset   # End the bisect session
```


---

# 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://smadi0x86-blog.gitbook.io/smadi0x86-playground/cloud-native/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.
