mirror of
https://github.com/mike-rambil/Advanced-Git.git
synced 2026-05-02 13:09:24 -05:00
Merge pull request #5 from mike-rambil/mike-rambil-patch-1
Update README.md
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
## How to Use `git push --force-with-lease` Safely
|
||||
|
||||
### 📑 Table of Contents
|
||||
- [How to Use `git push --force-with-lease` Safely](#how-to-use-git-push---force-with-lease-safely)
|
||||
- [Step 1: Understand the Problem](#step-1-understand-the-problem)
|
||||
- [Step 2: Use `git push --force-with-lease`](#step-2-use-git-push---force-with-lease)
|
||||
- [Step 3: Handle Rejected Pushes](#step-3-handle-rejected-pushes)
|
||||
- [Step 4: Best Practices](#step-4-best-practices)
|
||||
|
||||
### Step 1: Understand the Problem
|
||||
1. You and another developer are working on the same branch.
|
||||
2. You want to push your changes but are unsure if someone else has already pushed new commits.
|
||||
3. A standard `git push` might fail due to conflicts, and `git push --force` could overwrite others' work.
|
||||
|
||||
### Step 2: Use `git push --force-with-lease`
|
||||
1. Ensure your local branch is up to date:
|
||||
```sh
|
||||
git fetch origin
|
||||
```
|
||||
2. Attempt to push with `--force-with-lease`:
|
||||
```sh
|
||||
git push --force-with-lease
|
||||
```
|
||||
3. If no one else has pushed changes, your force push will succeed.
|
||||
4. If new commits exist on the remote, your push will be rejected, preventing accidental overwrites.
|
||||
|
||||
### Step 3: Handle Rejected Pushes
|
||||
1. If your push is rejected, pull the latest changes:
|
||||
```sh
|
||||
git pull --rebase origin main # Adjust branch name as needed
|
||||
```
|
||||
2. Resolve any conflicts and commit your updates.
|
||||
3. Retry pushing using `--force-with-lease`.
|
||||
|
||||
### Step 4: Best Practices
|
||||
1. **Use `--force-with-lease` instead of `--force`** to avoid overwriting others’ work.
|
||||
2. **Always fetch before pushing** to stay updated with remote changes.
|
||||
3. **Communicate with your team** when force-pushing is necessary.
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
# Contributors & Credits
|
||||
|
||||
## 👨👩👧👦Contributors
|
||||
|
||||
[@mike-rambil](https://github.com/mike-rambil)
|
||||
|
||||
## 📚 Credits & Authors
|
||||
[Sagil Bhatia](https://medium.com/@sahilsahilbhatia)
|
||||
|
||||
## 🔗 Blogs & Articles
|
||||
- [git-push-force-with-lease-vs-force](https://medium.com/@sahilsahilbhatia/git-push-force-with-lease-vs-force-ecae72601e80)
|
||||
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
# Advanced Git Commands
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you find a useful GIT command - be sure to sent a PR here as well :)
|
||||
|
||||
# ADVANCED GIT COMMANDS
|
||||
# Table of Contents
|
||||
|
||||
- [Advanced Git Commands](#advanced-git-commands)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Latest](#latest)
|
||||
- [Git Worktree Tutorial](#git-worktree-tutorial)
|
||||
- [📌 What is `git worktree`?](#-what-is-git-worktree)
|
||||
- [📌 `git push --force-with-lease`](#-git-push---force-with-lease)
|
||||
- [🔹 Problem](#-problem)
|
||||
- [🔹 Solution](#-solution)
|
||||
- [Tutorial](#tutorial)
|
||||
- [📌 Git Worktree Tutorial](#-git-worktree-tutorial)
|
||||
- [🔹 Check Existing Worktrees](#-check-existing-worktrees)
|
||||
- [🔹 Create a New Worktree](#-create-a-new-worktree)
|
||||
- [🔹 Remove a Worktree](#-remove-a-worktree)
|
||||
@@ -47,23 +53,42 @@
|
||||
- [**🐧 Bash**](#-bash)
|
||||
- [**🖥 PowerShell**](#-powershell)
|
||||
- [Miscellaneous](#miscellaneous)
|
||||
- [Contributors \& Credits](#contributors--credits)
|
||||
- [👨👩👧👦 Contributors](#-contributors)
|
||||
- [🧑💻 Credits \& Authors](#-credits--authors)
|
||||
- [📖 References \& Resources](#-references--resources)
|
||||
|
||||
|
||||
|
||||
# Advanced Git Commands
|
||||
|
||||
## Latest
|
||||
|
||||
- `git push --force-with-lease` - [Cancels git push if someone else did a commit on the same remote branch and safe guards `git push`](https://medium.com/@sahilsahilbhatia/git-push-force-with-lease-vs-force-ecae72601e80)
|
||||
- `git maintenance start` - [Runs a cronJob in background for the specified repo for periodic maintanence](https://git-scm.com/docs/git-maintenance)
|
||||
|
||||
# Git Worktree Tutorial
|
||||
## 📌 `git push --force-with-lease`
|
||||
|
||||
## 📌 What is `git worktree`?
|
||||
`git push --force-with-lease` ensures you don’t accidentally overwrite someone else’s work when force-pushing. It checks if the remote branch still matches what you last pulled. If someone else has pushed changes in the meantime, your push is rejected, preventing unintended data loss.
|
||||
|
||||
`git worktree` allows you to have multiple working directories linked to a single Git repository. This is useful when you need to work on multiple branches simultaneously without switching branches in the same directory.
|
||||
### 🔹 Problem
|
||||
|
||||
When users are within the same branch and they want to push to remote but not sure if there is a commit pushed from the other dev that might block you
|
||||
|
||||
### 🔹 Solution
|
||||
|
||||
use the ---force with lease flag while pushing to check it there is a push. If there is a push from the other person - your push to the same branch is cancelled.
|
||||
|
||||
### [Tutorial](./--force-with-lease.md)
|
||||
|
||||
> [Checkout Tutorial Here](./--force-with-lease.md)
|
||||
|
||||
## 📌 Git Worktree Tutorial
|
||||
|
||||
---
|
||||
|
||||
## 🔹 Check Existing Worktrees
|
||||
`git worktree` allows you to have multiple working directories linked to a single Git repository. This is useful when you need to work on multiple branches simultaneously without switching branches in the same directory.
|
||||
|
||||
### 🔹 Check Existing Worktrees
|
||||
|
||||
To see all active worktrees in your repository, use:
|
||||
|
||||
@@ -73,7 +98,7 @@ git worktree list
|
||||
|
||||
This will output a list of worktrees with their paths and branches.
|
||||
|
||||
## 🔹 Create a New Worktree
|
||||
### 🔹 Create a New Worktree
|
||||
|
||||
To create a new worktree for a branch, run:
|
||||
|
||||
@@ -95,7 +120,7 @@ If the branch does not exist, add -b to create it:
|
||||
git worktree add -b new-feature ../new-feature-branch
|
||||
```
|
||||
|
||||
## 🔹 Remove a Worktree
|
||||
### 🔹 Remove a Worktree
|
||||
|
||||
To remove a worktree (detach it from the repository), first remove the directory manually, then prune it:
|
||||
|
||||
@@ -111,7 +136,7 @@ rm -rf ../feature-branch
|
||||
git worktree prune
|
||||
```
|
||||
|
||||
## 🔹 Switch Between Worktrees
|
||||
### 🔹 Switch Between Worktrees
|
||||
|
||||
Simply change directories to the worktree you want to work in:
|
||||
|
||||
@@ -121,7 +146,7 @@ cd ../feature-branch
|
||||
|
||||
You can now work on this branch independently of the main repository directory.
|
||||
|
||||
## 🔹 Detach a Worktree Without Deleting It
|
||||
###🔹 Detach a Worktree Without Deleting It
|
||||
|
||||
```bash
|
||||
git worktree remove <worktree-path>
|
||||
@@ -133,7 +158,7 @@ Example:
|
||||
git worktree remove ../feature-branch
|
||||
```
|
||||
|
||||
## 🔹 Use Worktrees for Temporary Fixes
|
||||
### 🔹 Use Worktrees for Temporary Fixes
|
||||
|
||||
You can use worktrees to quickly fix bugs on a different branch without switching from your main working directory:
|
||||
|
||||
@@ -148,8 +173,8 @@ git worktree remove ../hotfix
|
||||
|
||||
```
|
||||
|
||||
# How to Use Git Submodules by Setting Up a New Submodule Repository and Pushing to It
|
||||
|
||||
## Git Submodules
|
||||
How to Use Git Submodules by Setting Up a New Submodule Repository and Pushing to It
|
||||
This guide walks you through:
|
||||
|
||||
- Creating a new Git submodule repository
|
||||
@@ -158,11 +183,11 @@ This guide walks you through:
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create the Git Submodule Repository
|
||||
### Step 1: Create the Git Submodule Repository
|
||||
|
||||
We need to create a new repository that will act as the submodule.
|
||||
|
||||
### 1. Initialize the Submodule Repository
|
||||
#### 1. Initialize the Submodule Repository
|
||||
|
||||
```bash
|
||||
mkdir my-submodule
|
||||
@@ -172,24 +197,24 @@ git init --bare
|
||||
|
||||
This sets up an empty bare repository, meaning it will only store Git data and be used as a remote.
|
||||
|
||||
### 2. Host it on GitHub (or any remote)
|
||||
#### 2. Host it on GitHub (or any remote)
|
||||
|
||||
- Go to GitHub (or GitLab/Bitbucket).
|
||||
- Create a new repository named my-submodule.
|
||||
- Copy the remote URL (e.g., <git@github.com>:your-user/my-submodule.git).
|
||||
|
||||
### 3. Push the Bare Repo to Remote
|
||||
#### 3. Push the Bare Repo to Remote
|
||||
|
||||
```bash
|
||||
git remote add origin git@github.com:your-user/my-submodule.git
|
||||
git push --set-upstream origin main
|
||||
```
|
||||
|
||||
## Step 2: Add the Submodule to Another Repo
|
||||
### Step 2: Add the Submodule to Another Repo
|
||||
|
||||
Now, let’s integrate this submodule into a main repository.
|
||||
|
||||
### 1. Initialize and Clone the Main Repository
|
||||
#### 1. Initialize and Clone the Main Repository
|
||||
|
||||
```bash
|
||||
mkdir main-repo
|
||||
@@ -197,7 +222,7 @@ cd main-repo
|
||||
git init
|
||||
```
|
||||
|
||||
### 2. Add the Submodule
|
||||
#### 2. Add the Submodule
|
||||
|
||||
```bash
|
||||
git submodule add git@github.com:your-user/my-submodule.git submodules/my-submodule
|
||||
@@ -205,7 +230,7 @@ git submodule add git@github.com:your-user/my-submodule.git submodules/my-submod
|
||||
|
||||
This clones the submodule into the submodules/my-submodule directory inside the main repo.
|
||||
|
||||
### 3. Commit and Push
|
||||
#### 3. Commit and Push
|
||||
|
||||
```bash
|
||||
git add .gitmodules submodules/my-submodule
|
||||
@@ -213,17 +238,17 @@ git commit -m "Added submodule my-submodule"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## Step 3: Add Files and Push to the Submodule
|
||||
### Step 3: Add Files and Push to the Submodule
|
||||
|
||||
Now, let’s add files to the submodule from the main repo.
|
||||
|
||||
### 1. Navigate into the Submodule
|
||||
#### 1. Navigate into the Submodule
|
||||
|
||||
```bash
|
||||
cd submodules/my-submodule
|
||||
```
|
||||
|
||||
### 2. Add Files to the Submodule
|
||||
#### 2. Add Files to the Submodule
|
||||
|
||||
```bash
|
||||
echo "Hello from the submodule!" > file.txt
|
||||
@@ -231,23 +256,23 @@ git add file.txt
|
||||
git commit -m "Added file to submodule"
|
||||
```
|
||||
|
||||
### 3. Push the Changes to the Submodule Repository
|
||||
#### 3. Push the Changes to the Submodule Repository
|
||||
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## Step 4: Commit the Updated Submodule in the Main Repo
|
||||
### Step 4: Commit the Updated Submodule in the Main Repo
|
||||
|
||||
Once the submodule has new changes, the main repository needs to recognize it.
|
||||
|
||||
### 1. Move Back to Main Repo
|
||||
#### 1. Move Back to Main Repo
|
||||
|
||||
```bash
|
||||
cd ../..
|
||||
```
|
||||
|
||||
### 2. Stage and Commit the Submodule Update
|
||||
#### 2. Stage and Commit the Submodule Update
|
||||
|
||||
```bash
|
||||
git add submodules/my-submodule
|
||||
@@ -255,7 +280,7 @@ git commit -m "Updated submodule to latest commit"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## Step 5: Cloning and Initializing Submodules
|
||||
### Step 5: Cloning and Initializing Submodules
|
||||
|
||||
If you or someone else clones the main repo, you need to initialize the submodules:
|
||||
|
||||
@@ -276,48 +301,57 @@ git submodule update --init --recursive
|
||||
- ✅ Pushed files from the main repo into the submodule
|
||||
- ✅ Updated the submodule reference in the main repo
|
||||
|
||||
|
||||
## Difference Between `git submodule update --remote --merge` and `git submodule update --init --recursive`
|
||||
|
||||
Both commands update submodules, but they work differently.
|
||||
|
||||
✅ 1️⃣ `git submodule update --remote --merge`
|
||||
|
||||
```bash
|
||||
git submodule update --remote --merge
|
||||
```
|
||||
|
||||
📌 **What It Does:**
|
||||
|
||||
- Pulls the latest commit from the remote branch of the submodule.
|
||||
- Merges that commit into your local submodule.
|
||||
- Updates the submodule folder to match the latest remote version.
|
||||
|
||||
🛠 **When to Use It**
|
||||
|
||||
- When you want to fetch the latest changes from the submodule’s remote repo.
|
||||
- Useful if the submodule is actively being updated and you want to sync with the latest version.
|
||||
|
||||
🚀 **Example**
|
||||
|
||||
- Your submodule (`whk-script-library`) is behind the remote repository.
|
||||
- Running `git submodule update --remote --merge` fetches and merges the latest changes.
|
||||
- The submodule now tracks the latest remote commit.
|
||||
|
||||
✅ 2️⃣ `git submodule update --init --recursive`
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
📌 **What It Does:**
|
||||
|
||||
- Ensures that all submodules are initialized (`--init`).
|
||||
- Updates submodules to the exact commit referenced in the main repository.
|
||||
- Recursively initializes nested submodules (`--recursive`).
|
||||
|
||||
🛠 **When to Use It**
|
||||
|
||||
- When you just cloned the main repository and need to fetch and initialize submodules.
|
||||
- Ensures that all submodules match the commit stored in the main repo (even if they are outdated).
|
||||
- Best for setting up a project that includes submodules.
|
||||
|
||||
🚀 **Example**
|
||||
|
||||
- You cloned `whk-wms`, but the `whk-script-library` submodule is empty.
|
||||
- Running `git submodule update --init --recursive` initializes and updates it to the expected commit.
|
||||
- The submodule now matches the commit tracked in the main repo, not necessarily the latest commit from the remote.
|
||||
|
||||
|
||||
# Delete Untracked Files and Folders
|
||||
|
||||
To delete untracked files and folders, use the following methods:
|
||||
@@ -419,18 +453,25 @@ What this does:
|
||||
- `git request-pull <start> <url> <end>`: Generate a request to pull changes into a repository.
|
||||
|
||||
# 🛠 **View and Clean Up Local Git Branches**
|
||||
|
||||
## **🐧 Bash**
|
||||
|
||||
List Local Branches Without a Remote Connection.
|
||||
```git branch -vv | grep -E '^\s*\S+\s+[^\[]+$'```
|
||||
`git branch -vv | grep -E '^\s*\S+\s+[^\[]+$'`
|
||||
Automatically Delete Local Branches Without Remote Tracking.
|
||||
|
||||
```
|
||||
git branch -vv | grep -E '^\s*\S+\s+[^\[]+$' | awk '{print $1}' | xargs git branch -D
|
||||
```
|
||||
View Local Branches That Had Their Remote Deleted (Ex: PR Merged & Deleted in remote but still exist in local).**
|
||||
|
||||
View Local Branches That Had Their Remote Deleted (Ex: PR Merged & Deleted in remote but still exist in local).\*\*
|
||||
|
||||
```
|
||||
git branch -vv | grep ': gone]'
|
||||
```
|
||||
```
|
||||
|
||||
Delete Stale Local Branches That Had Their Remote Deleted.
|
||||
|
||||
```
|
||||
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D
|
||||
```
|
||||
@@ -438,28 +479,34 @@ git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D
|
||||
---
|
||||
|
||||
## **🖥 PowerShell**
|
||||
List Local Branches Without a Remote Connection.
|
||||
```
|
||||
git branch -vv | Select-String -NotMatch "origin/"
|
||||
```
|
||||
Automatically Delete Local Branches Without Remote Tracking
|
||||
```
|
||||
git branch -vv | Select-String -NotMatch "origin/" | ForEach-Object {
|
||||
$branch = ($_ -split "\s+")[1]
|
||||
git branch -D $branch
|
||||
}
|
||||
```
|
||||
|
||||
View Local Branches That Had Their Remote Deleted (Ex: PR Merged & Deleted in remote but still exist in local).**
|
||||
List Local Branches Without a Remote Connection.
|
||||
|
||||
```
|
||||
git branch -vv | Select-String -NotMatch "origin/"
|
||||
```
|
||||
|
||||
Automatically Delete Local Branches Without Remote Tracking
|
||||
|
||||
```
|
||||
git branch -vv | Select-String -NotMatch "origin/" | ForEach-Object {
|
||||
$branch = ($_ -split "\s+")[1]
|
||||
git branch -D $branch
|
||||
}
|
||||
```
|
||||
|
||||
View Local Branches That Had Their Remote Deleted (Ex: PR Merged & Deleted in remote but still exist in local).\*\*
|
||||
|
||||
```
|
||||
git branch -vv | Select-String ": gone\]"
|
||||
```
|
||||
|
||||
Delete Stale Local Branches That Had Their Remote Deleted.**
|
||||
|
||||
Delete Stale Local Branches That Had Their Remote Deleted.\*\*
|
||||
|
||||
```
|
||||
git fetch -p && git branch -vv | Select-String ': gone]' | ForEach-Object { $_.ToString().Trim().Split()[0] } | ForEach-Object { git branch -D $_ }
|
||||
```
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
- `git archive --format=zip --output=<file.zip> <tree-ish>`: Create an archive of files from a named tree.
|
||||
@@ -471,3 +518,30 @@ git fetch -p && git branch -vv | Select-String ': gone]' | ForEach-Object { $_.T
|
||||
- `git bundle verify <file>`: Verify the integrity of a bundle file.
|
||||
- `git bundle unbundle <file>`: Extract a bundle into a repository.
|
||||
- `git rm --cached -r <file/folder>`: Removes Git tracking without deleting files from local machine which prevents Git from tracking future changes if it’s added to .gitignore.(Ex: most useful for deleting .env when you accidentally push it to remote)
|
||||
|
||||
---
|
||||
|
||||
## Contributors & Credits
|
||||
|
||||
> [!NOTE]
|
||||
> Add yourself, your links you have used, or even your blogs if you have some or is an **author**
|
||||
|
||||
|
||||
#### [👨👩👧👦 Contributors](./Contributors&Credits.md)
|
||||
A list of individuals who have contributed to this project.
|
||||
|
||||
> 👨👩👧👦 [View Contributors](./Contributors&Credits.md#contributors)
|
||||
|
||||
#### [🧑💻 Credits & Authors](./Contributors&Credits.md#credits-authors)
|
||||
Acknowledgment of the original authors.
|
||||
|
||||
> 🧑💻 [View Credits & Authors](./Contributors&Credits.md#credits-authors)
|
||||
|
||||
#### [📖 References & Resources](./Contributors&Credits.md#references-resources)
|
||||
A collection of blogs, articles, and materials used to learn more about Git.
|
||||
|
||||
> 📖 [View References & Resources](./Contributors&Credits.md#references-resources)
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user