# Git and GitHub Advanced

#### **Branching Strategy**

In Git, branches are a powerful way to work on different features or fixes independently without affecting the main codebase. A good branching strategy is crucial for successful collaboration, especially in large teams. Some common branching strategies include:

1. **Git Flow**: A popular strategy that uses long-lived branches for main development (`main` or `master`) and separate branches for features, releases, and hotfixes. This approach provides clear separation between production-ready code and work-in-progress.
    
2. **GitHub Flow**: A simpler approach that involves a single `main` branch and short-lived feature branches. Developers create feature branches off the `main` branch, and once the feature is complete, it is merged back into `main` via a pull request.
    
3. **Trunk-Based Development**: This strategy involves having a single branch (often `main` or `trunk`) where all developers commit their changes. Feature branches are short-lived, and changes are integrated into the `main` branch frequently. This approach emphasizes continuous integration and deployment.
    

Choosing the right branching strategy depends on your team's workflow, project size, and release schedule.

#### **Revert vs. Reset**

Both `git revert` and `git reset` are used to undo changes, but they work differently and serve distinct purposes.

* `git revert`: This command creates a new commit that undoes the changes of a previous commit. It is safe for collaborative workflows because it preserves the commit history. `git revert` is ideal when you want to undo changes but still keep a record of them.
    
    ```bash
    git revert <commit-hash>
    ```
    
* `git reset`: This command undoes changes by moving the branch pointer to a previous commit. It can modify the commit history, making it potentially destructive in a shared repository. `git reset` is best used in private branches or before changes are pushed to a remote repository.
    
    ```bash
    git reset --soft <commit-hash>
    git reset --hard <commit-hash>
    ```
    

#### **Merge vs. Rebase**

When integrating changes from one branch into another, Git offers two primary methods: merge and rebase.

* **Merge**: Merging combines the changes from one branch into another by creating a merge commit. This method preserves the history of both branches, showing a clear record of when and how branches were integrated.
    
    ```bash
    git merge <branch-name>
    ```
    
* **Rebase**: Rebasing moves or combines commits from one branch onto another, creating a linear history. It eliminates unnecessary merge commits, making the history cleaner. However, rebasing can rewrite commit history, so it's best used on local or feature branches before they are shared with others.
    
    ```bash
    git rebase <branch-name>
    ```
    
    **When to Use Merge vs. Rebase**:
    
    * Use **merge** when you want to preserve the context of branch development and are okay with a non-linear history.
        
    * Use **rebase** when you want a clean, linear history and are working on private or feature branches.
        

#### **Cherry-Pick**

The `git cherry-pick` command allows you to apply changes from a specific commit to another branch without merging the entire branch. This is useful when you want to apply a bug fix or feature from one branch to another without bringing in unrelated changes.

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

#### **Stash**

The `git stash` command temporarily saves your uncommitted changes, allowing you to switch branches or work on something else without losing your progress. Later, you can apply the stashed changes back to your working directory.

* **Stash changes**:
    
    ```bash
    git stash
    ```
    
* **Apply stashed changes**:
    
    ```bash
    git stash apply
    ```
    
* **Pop stashed changes (apply and remove from stash list)**:
    
    ```bash
    git stash pop
    ```
    

#### **Squash Commits**

Squashing commits is the process of combining multiple commits into a single one. This is often done during a rebase to clean up commit history before merging a feature branch into the main branch.

```bash
git rebase -i <base-commit-hash>
```

During the interactive rebase process, you can mark commits to be squashed, combining them into one.

#### **Merge Conflict**

A merge conflict occurs when Git is unable to automatically resolve differences between branches. This happens when two branches modify the same lines in a file or when one branch deletes a file that the other modifies. Resolving merge conflicts involves manually reviewing the conflicting changes and deciding which ones to keep.

* **Identify conflicts**: After a failed merge or rebase, Git will mark the conflicting files.
    
    ```bash
    git status
    ```
    
* **Resolve conflicts**: Open the conflicting files and manually resolve the differences. Git uses markers to indicate the conflicting sections.
    
* **Mark as resolved**: Once you've resolved the conflicts, stage the changes.
    
    ```bash
    git add <resolved-file>
    ```
    
* **Continue the merge or rebase**:
    
    ```bash
    git merge --continue
    git rebase --continue
    ```
