git-branching.md (12901B)
1 --- 2 title: "Git Branching" 3 description: "Branch workflows: create/switch, track remotes, merge vs rebase, and moving edits between branches." 4 category: git-workflow 5 tags: [git, branching, workflow] 6 tools: [git] 7 difficulty: intermediate 8 updated: "2026-08-09" 9 source: "vault:Git/Branches Expanded.md" 10 --- 11 12 # Git Branching 13 14 This guide covers a multi-vault branching model: one GitHub repo holding several completely different working trees, each on its own orphan branch. Switching branch swaps the entire file tree. 15 16 > **Use case —** One GitHub repo, multiple completely different vaults (e.g. Obsidian), each living on its own branch with totally different files. Each branch = its own world. Switching branch = switching vault. Zero overlap. 17 18 > **Repository architecture —** 19 > ```text 20 > your-repo (on GitHub) 21 > │ 22 > ├── main ──────────────────► Personal Vault (your notes, templates etc) 23 > │ 24 > ├── HTB-Labs ──────────────► HTB Vault (writeups, lab notes etc) 25 > │ 26 > └── Work-Notes ────────────► Work Vault (completely different again) 27 > ``` 28 29 > **Warning — Obsidian users, branch-switching:** Always close the current vault in Obsidian **before** running `git checkout`. Obsidian can recreate files or get confused when files suddenly change under it. After switching branch, reopen Obsidian and point it to the same folder. 30 31 > **Tip — Golden rules for multi-vault repos:** 32 > 1. Always run `git branch` before committing — make sure you're on the right vault. 33 > 2. Use `--orphan` for new vaults — never branch off main or you'll inherit its files. 34 > 3. Close Obsidian before switching branches to avoid file conflicts. 35 > 4. Push regularly — GitHub is your backup for every vault. 36 37 > **Overview —** Git is a distributed version control system, used here to manage isolated vaults on separate branches within a single repository. 38 > 1. `--orphan` creates a branch with no history and no inherited files. 39 > 2. `git rm -rf .` wipes all files after orphan creation for a clean slate. 40 > 3. `git reset --hard` force-syncs local state to match a remote or previous commit. 41 > 4. Each branch operates as a fully independent file tree. 42 43 ## Part 1 — Initial Setup (First Time) 44 45 **Step 1 — Set up your Main vault branch first** 46 47 ```bash 48 # Initialise the repo if you haven't already 49 git init 50 git remote add origin https://github.com/yourusername/your-repo.git 51 52 # Add all your main vault files 53 git add . 54 git commit -m "Initial main vault setup" 55 git push -u origin main 56 ``` 57 58 > **Command breakdown —** 59 > 1. `git init`: initialises a new local Git repository in the current directory. 60 > 2. `git remote add origin <url>`: links your local repo to the remote GitHub repository. 61 > 3. `git add .`: stages all files in the current directory for commit. 62 > 4. `git commit -m "..."`: commits staged files with a descriptive message. 63 > 5. `git push -u origin main`: pushes to GitHub and sets `origin/main` as the upstream tracking branch. 64 65 **Step 2 — Create a completely empty new branch (e.g. HTB-Labs)** 66 67 ```bash 68 # Create orphan branch — NO history, NO files carried over from main 69 git checkout --orphan HTB-Labs 70 71 # Wipe every file that carried over from main 72 git rm -rf . 73 ``` 74 75 > **Command breakdown —** 76 > 1. `git checkout --orphan HTB-Labs`: creates a new branch with zero commit history — files from the current branch are present in the working tree but untracked, so the next step wipes them. 77 > 2. `git rm -rf .`: recursively force-removes all files from the working tree and staging area, leaving a completely blank slate. 78 > 3. `main` is entirely untouched by this operation. 79 80 > **Result —** You now have a completely blank slate on the `HTB-Labs` branch. The `main` branch and all its files remain untouched. 81 82 **Step 3 — Add your second vault files** 83 84 ```bash 85 # Create your new vault structure 86 mkdir HTB-Labs 87 echo "# HTB Labs Vault" > README.md 88 89 # Add and commit 90 git add . 91 git commit -m "Initial HTB Labs vault setup" 92 93 # Push to GitHub 94 git push -u origin HTB-Labs 95 ``` 96 97 > **Command breakdown —** 98 > 1. `mkdir HTB-Labs`: creates a new directory for the vault structure. 99 > 2. `echo "# HTB Labs Vault" > README.md`: creates a minimal README as the first file, required for an initial commit. 100 > 3. `git push -u origin HTB-Labs`: pushes the new orphan branch to GitHub and sets tracking — `-u` only needed on the first push of a new branch. 101 102 ## Part 2 — Switching Between Vaults 103 104 ```bash 105 git checkout main # Switch to Personal Vault 106 git checkout HTB-Labs # Switch to HTB Vault 107 git checkout Work-Notes # Switch to Work Vault 108 ``` 109 110 > **Command breakdown —** 111 > 1. `git checkout <branch>`: switches the working directory to the specified branch, replacing all files with that branch's contents. 112 > 2. Because each branch was created with `--orphan`, each has a completely different file tree — switching branches is equivalent to switching between entirely different vaults. 113 114 > **Warning — Before every switch:** Run `git status` first to confirm you have no uncommitted changes. Unsaved changes can carry over or cause conflicts when switching branches. 115 116 ## Part 3 — Saving Changes to Each Vault 117 118 > **Important — Verify your branch before committing:** Always confirm you are on the correct branch before staging or committing. Use `git branch` or `git status`. 119 120 ```bash 121 # Check which branch/vault you are on 122 git branch 123 124 # Save changes to whichever vault you're currently on 125 git add . 126 git commit -m "Update HTB writeup for box XYZ" 127 git push 128 ``` 129 130 > **Command breakdown —** 131 > 1. `git branch`: lists all local branches with an asterisk (`*`) next to the currently active one. 132 > 2. `git add .`: stages all new, modified, and deleted files in the working directory. 133 > 3. `git commit -m "..."`: creates a snapshot of staged changes — use descriptive messages for easy history navigation. 134 > 4. `git push`: pushes committed changes to the tracked remote branch on GitHub. 135 136 **Saving to a specific vault (ensuring correct branch)** 137 138 ```bash 139 # Switch to the vault you want to update 140 git checkout HTB-Labs 141 142 # Make your changes, then save 143 git add . 144 git commit -m "Add new lab notes" 145 git push 146 ``` 147 148 > **Note —** Explicitly checking out the target branch before making changes eliminates the risk of committing to the wrong vault. This pattern — switch, change, commit, push — should be the standard workflow for every vault update. 149 150 ## Part 4 — Adding More Vaults Later 151 152 > **Important — Always use orphan branches for new vaults:** Never use `git checkout -b` to create a new vault branch — it inherits all files from the current branch. Always use `--orphan` to start with a completely empty branch. 153 154 ```bash 155 # 1. Create a new empty branch 156 git checkout --orphan Work-Notes 157 158 # 2. Wipe everything (removes any leftover files) 159 git rm -rf . 160 161 # 3. Create your new vault files 162 mkdir Work-Notes-Vault 163 echo "# Work Notes" > README.md 164 165 # 4. Commit and push 166 git add . 167 git commit -m "Initial Work Notes vault" 168 git push -u origin Work-Notes 169 ``` 170 171 > **Command breakdown —** 172 > 1. `git checkout --orphan Work-Notes`: creates a new isolated branch with no shared history with any other branch. 173 > 2. `git rm -rf .`: required after every orphan creation to remove working-tree files that carried over. 174 > 3. Steps 3 and 4 follow the same pattern as any initial vault setup — create a minimal structure, then commit and push. 175 176 ## Part 5 — Restoring Deleted Files 177 178 > **Tip — Best all-in-one fix, force sync with GitHub:** When in doubt, this restores your branch to exactly match the remote: 179 > ```bash 180 > git fetch --all 181 > git reset --hard origin/HTB-Labs # Replace with your branch name 182 > ``` 183 184 **Scenario 1 — Deleted files, not yet staged** 185 186 ```bash 187 git restore . 188 ``` 189 190 > **Note —** `git restore .` discards all unstaged changes in the working directory, restoring files to their last committed state. Safe to use — only affects uncommitted, unstaged changes. 191 192 **Scenario 2 — Deleted and staged, NOT yet committed** 193 194 ```bash 195 git restore --staged --worktree . 196 ``` 197 198 > **Note —** `--staged` removes files from the staging area (index); `--worktree` also restores the actual files in the working directory. Combines unstaging and file restoration in a single command. 199 200 **Scenario 3 — Deleted, committed, NOT yet pushed** 201 202 ```bash 203 git reset --hard HEAD~1 # Roll back 1 commit 204 ``` 205 206 > **Note —** `git reset --hard` resets both the commit history and the working directory to the specified point. `HEAD~1` refers to one commit before the current `HEAD` — replace `1` with however many commits you need to roll back. This rewrites local history — safe because the bad commit has not been pushed yet. 207 208 **Scenario 4 — Deleted, committed AND pushed** 209 210 ```bash 211 git fetch --all 212 git reset --hard origin/main # Force match the remote 213 ``` 214 215 > **Command breakdown —** 216 > 1. `git fetch --all`: downloads all latest data from every remote branch without merging anything. 217 > 2. `git reset --hard origin/main`: forces the local branch to exactly match the remote state, discarding any local divergence. 218 > 3. Replace `main` with whichever branch name you need to restore. 219 220 > **Warning — Destructive operation:** `git reset --hard` permanently discards local changes and commits ahead of the reset point. Ensure you do not need any of that local data before running this command. 221 222 ## Part 6 — Managing Branches 223 224 | Action | Command | 225 |---|---| 226 | See all branches | `git branch -a` | 227 | See which branch you're on | `git branch` | 228 | Rename a branch | `git branch -m old-name new-name` | 229 | Delete local branch | `git branch -d branch-name` | 230 | Force delete local branch | `git branch -D branch-name` | 231 | Delete branch from GitHub | `git push origin --delete branch-name` | 232 | See last commit on each branch | `git branch -v` | 233 234 > **Warning — Deleting branches:** 235 > 1. `git branch -d` refuses to delete a branch with unmerged changes — a safety net. 236 > 2. `git branch -D` force-deletes regardless — use only when certain the data is not needed. 237 > 3. Deleting a remote branch with `git push origin --delete` is permanent — GitHub has no recycle bin. 238 239 ## Part 7 — Branch Naming Conventions 240 241 > **Tip — Naming rules:** Keep names clean, lowercase, no spaces — use hyphens `-` as separators. 242 243 | Vault / Purpose | Good Branch Name | 244 |---|---| 245 | Personal Obsidian vault | `main` or `personal-vault` | 246 | HTB / CTF notes | `HTB-Labs` | 247 | Work notes | `work-notes` | 248 | Study notes | `study-vault` | 249 | New feature / test | `feature/new-template` | 250 | Bug / fix | `bugfix/broken-link` | 251 | Archive / old version | `archive/2024-vault` | 252 253 ## Part 8 — Quick Reference Card 254 255 ```bash 256 # ── CREATING ────────────────────────────────────────── 257 git checkout --orphan branch-name # New empty branch (no history) 258 git rm -rf . # Wipe files after orphan create 259 git checkout -b branch-name # New branch copied from current 260 261 # ── SWITCHING ───────────────────────────────────────── 262 git checkout branch-name # Switch to vault/branch 263 git checkout - # Jump back to previous branch 264 265 # ── SAVING ──────────────────────────────────────────── 266 git add . # Stage all changes 267 git commit -m "your message" # Commit changes 268 git push # Push to GitHub 269 git push -u origin branch-name # First push of a new branch 270 271 # ── SYNCING ─────────────────────────────────────────── 272 git pull # Pull latest from GitHub 273 git fetch --all # Fetch all remote branches 274 275 # ── RESTORING ───────────────────────────────────────── 276 git restore . # Undo unstaged deletions 277 git reset --hard origin/branch-name # Force match GitHub 278 git reset --hard HEAD~1 # Roll back 1 commit 279 280 # ── CLEANUP ─────────────────────────────────────────── 281 git branch -d branch-name # Delete local branch 282 git push origin --delete branch-name # Delete remote branch 283 ``` 284 285 ## References 286 287 - [Git Official Documentation](https://git-scm.com/doc) 288 - [git-checkout Reference](https://git-scm.com/docs/git-checkout) 289 - [git-branch Reference](https://git-scm.com/docs/git-branch) 290 - [git-reset Reference](https://git-scm.com/docs/git-reset) 291 - [git-restore Reference](https://git-scm.com/docs/git-restore)