Feature Branch Workflow
Practice the complete lifecycle of a feature branch: create, develop, push, PR, merge, and cleanup.
Setup
Use an existing GitHub-connected repository or create one:
bash1$ mkdir branch-practice && cd branch-practice2$ git init3$ echo "# Branch Practice" > README.md4$ git add README.md5$ git commit -m "docs: initial README"67# Connect to GitHub (use your own repo)8$ gh repo create your-username/branch-practice --private --source=. --remote=origin --push
Exercise 1: Create a Feature Branch
Update Main First
bash1$ git switch main2$ git pull --ff-only3Already up to date.
Create the Branch
bash1$ git checkout -b feature/add-greeting2Switched to a new branch 'feature/add-greeting'
Verify
bash1$ git branch2 main3* feature/add-greeting
Exercise 2: Develop the Feature
Create a File
bash1$ cat <<'EOF' > greeting.js2function greet(name) {3 const hour = new Date().getHours();45 if (hour < 12) {6 return `Good morning, ${name}!`;7 } else if (hour < 18) {8 return `Good afternoon, ${name}!`;9 } else {10 return `Good evening, ${name}!`;11 }12}1314module.exports = { greet };15EOF
First Commit
bash1$ git add greeting.js2$ git commit -m "feat: add time-aware greeting function"3[feature/add-greeting 2a3b4c5] feat: add time-aware greeting function4 1 file changed, 14 insertions(+)5 create mode 100644 greeting.js
Add More to the Feature
bash1$ cat <<'EOF' > index.js2const { greet } = require('./greeting');34const name = process.argv[2] || 'World';5console.log(greet(name));6EOF78$ git add index.js9$ git commit -m "feat: add CLI entry point"10[feature/add-greeting 3b4c5d6] feat: add CLI entry point11 1 file changed, 4 insertions(+)12 create mode 100644 index.js
View Branch History
bash1$ git log --oneline23b4c5d6 (HEAD -> feature/add-greeting) feat: add CLI entry point32a3b4c5 feat: add time-aware greeting function41a2b3c4 (origin/main, main) docs: initial README
Exercise 3: Push and Create PR
Push Branch to Remote
bash1$ git push -u origin feature/add-greeting2Enumerating objects: 7, done.3...4To github.com:your-username/branch-practice.git5 * [new branch] feature/add-greeting -> feature/add-greeting6Branch 'feature/add-greeting' set up to track remote branch 'feature/add-greeting' from 'origin'.
Create Pull Request
Option A: Using gh CLI
bash1$ gh pr create --fill2Creating pull request for feature/add-greeting into main in your-username/branch-practice34https://github.com/your-username/branch-practice/pull/1
Option B: Custom title and body
bash1$ gh pr create --title "Add time-aware greeting" --body "This PR adds a greeting function that says good morning/afternoon/evening based on the current time.23## Changes4- greeting.js: Time-aware greeting function5- index.js: CLI entry point67## Testing8\`\`\`bash9node index.js Alice10\`\`\`"
View PR
bash1$ gh pr view2Add time-aware greeting #13Open • your-username wants to merge 2 commits into main from feature/add-greeting4...
Exercise 4: Merge the PR
Using Squash Merge
bash1$ gh pr merge --squash --delete-branch2✔ Squashed and merged pull request #1 (Add time-aware greeting)3✔ Deleted branch feature/add-greeting and switched to branch main
This:
- Squashes all commits into one
- Merges to main
- Deletes the remote branch
- Switches you to main
Verify Merge
bash1$ git pull2$ git log --oneline34c5d6e7 (HEAD -> main, origin/main) Add time-aware greeting (#1)41a2b3c4 docs: initial README
Notice: Two commits became one squashed commit.
Exercise 5: Clean Up Local Branch
The remote branch was deleted, but check local:
bash1$ git branch2* main
If the branch still existed locally:
bash1$ git branch -d feature/add-greeting2Deleted branch feature/add-greeting (was 3b4c5d6).
Prune Stale Remote References
bash1$ git fetch --prune
This removes local references to deleted remote branches.
Exercise 6: Second Feature (Practice)
Repeat the workflow with another feature:
bash1# 1. Create branch2$ git checkout -b feature/add-farewell34# 2. Add code5$ cat <<'EOF' >> greeting.js67function farewell(name) {8 return `Goodbye, ${name}! See you next time.`;9}1011module.exports = { greet, farewell };12EOF1314# 3. Commit15$ git add greeting.js16$ git commit -m "feat: add farewell function"1718# 4. Push19$ git push -u origin feature/add-farewell2021# 5. Create PR22$ gh pr create --fill2324# 6. Merge25$ gh pr merge --squash --delete-branch2627# 7. Verify28$ git pull29$ git log --oneline
Final Verification
Your history should show clean, squashed merges:
bash1$ git log --oneline --graph2* 5d6e7f8 (HEAD -> main, origin/main) Add farewell function (#2)3* 4c5d6e7 Add time-aware greeting (#1)4* 1a2b3c4 docs: initial README
Checklist
- Created feature branch from main
- Made multiple commits on the branch
- Pushed branch to remote with
-u - Created PR using
gh pr create - Merged PR with
--squash --delete-branch - Local main is up to date after merge
- Completed second feature for practice
Cleanup
If you want to delete the practice repository:
bash1$ gh repo delete your-username/branch-practice --yes2$ cd ..3$ rm -rf branch-practice
Key Takeaway
The feature branch workflow—branch, commit, push, PR, merge, delete—is the foundation of collaborative development. Practice it until it's automatic.