🧩 Git & GitHub Mastery
This guide covers advanced Git usage and Pull Request workflows for professional collaboration and project management.
1️⃣ Branching Strategy
-
Main (
main)- Stable, deployable code only.
- No direct commits; merge tested branches only.
-
Development (
development)- Active integration branch for ongoing work.
- Keeps
mainrelease-ready while features are still being tested. - Useful for pre-release work, CI validation, and team collaboration.
-
Feature branches (
feature/<name>)- One branch per feature or improvement.
- Clear naming convention improves collaboration.
-
Fix branches (
fix/<name>/bug/<name>)- Focused bug fixes.
- Keep short-lived and small.
-
Hotfix branches (
hotfix/<name>)- Urgent production fixes.
- Merge into
mainimmediately after verification.
Why a development branch is useful
- Keeps
mainstable and release-ready. - Allows safe experimentation without affecting production-ready code.
- Makes collaboration easier by giving teammates a clear integration branch.
- Supports a professional workflow: feature branches ->
development->main. - Simplifies releases when it is time to promote tested work into
main.
Recommended branch flow
main # Always stable
\
development # Active development branch
\
feature/<name> # Feature or fix branches
Creating a branch safely
git checkout development
git pull origin development
git checkout -b feature/<name>
Creating the development branch
git checkout main
git pull origin main
git checkout -b development
git push -u origin development
2️⃣ Commit Best Practices
Use descriptive prefixes:
feat:new featurefix:bug fixchore:tooling/dependencydocs:documentationrefactor:code restructuretest:tests
Keep commits small and focused.
Stage changes selectively:
git add -p
Amend commits if necessary:
git commit --amend
Reword commits:
git commit --amend -m "new message"
3️⃣ Pull Requests (PRs)
Push your branch:
git push origin feature/<name>
Open a PR:
- Target branch:
developmentfor normal feature work,mainfor tested releases or hotfixes. - Include:
- Clear description of the change
- Context for why it exists
- Steps to verify
Code review:
- Assign reviewers
- Respond to feedback
- Update branch as needed
Merge PR:
Rebase or squash commits for clean history:
git fetch origin
git rebase origin/main
- Resolve conflicts carefully
- Test after rebasing
Alternatively, pull with merge to preserve history:
git fetch origin
git pull --no-ff origin/main
Typical flow:
- Create a feature branch from
development. - Open a PR from
feature/<name>intodevelopment. - Test and validate changes on
development. - Open a PR from
developmentintomainwhen ready to release.
Example merge flow:
git checkout -b feature/login development
# work, commit, push
git push origin feature/login
git checkout development
git pull origin development
git merge --no-ff feature/login
git push origin development
git checkout main
git pull origin main
git merge --no-ff development
git tag v0.1.0
git push origin main --tags
4️⃣ Rebasing: When It's Safe and When It Isn't
Rebasing IS SAFE:
- ✅ On your personal/feature branch before merging into shared branches
- ✅ When only you have checked out that branch
- ✅ To clean up commit history before creating a PR
- ✅ Example:
git rebase origin/developmenton yourfeature/loginbranch
Rebasing IS DANGEROUS:
- ❌ After merging into
main,development, or shared branches - ❌ On branches other people are building on top of
- ❌ If you've already pushed to shared branches and teammates have pulled
- ❌ Never
git push -fto shared branches
Why? Rebasing rewrites history. On shared branches, this breaks everyone's local copies and causes merge conflicts and lost work.
Safe rule: Rebase your feature branch before merging. Once merged into a shared branch, don't rebase it—use merges instead.
5️⃣ Advanced Git Techniques
Interactive rebase to clean up commit history:
git rebase -i HEAD~5
Cherry-pick a single commit across branches:
git cherry-pick <commit-hash>
Stashing changes when switching branches:
git stash
git checkout main
git stash pop
Reset to undo changes safely:
git reset --soft HEAD~1 # keep changes staged
git reset --hard HEAD~1 # discard changes
Safety note:
git reset --hardpermanently drops uncommitted changes in tracked files.- Prefer non-destructive rollback first:
git restore --staged <file>andgit restore <file>. - If you used a destructive reset by mistake, check recovery with
git reflogand restore withgit reset --hard <reflog-commit>.
6️⃣ Collaboration & Hygiene
- Keep branches short-lived; merge frequently.
- Branch feature work from
development, not directly frommain. - Pull latest changes before starting work:
git fetch origin
git rebase origin/development
- Keep
maindeployable at all times. - Merge to
mainonly after testing is complete. - Commit frequently with clear messages.
- Use CI/CD pipelines to validate PRs before merging.
- Tag releases for easier version management.
- Delete branches after merging to keep repo clean.
7️⃣ Summary
- Branch responsibly and name clearly.
- Use
developmentas the integration branch for active work. - Commit small, descriptive, and focused.
- Use PRs for code review and safe merging.
- Keep
mainstable and release-ready. - Rebase and squash to maintain a clean history.
- Tag releases when promoting tested work to
main. - Automate where possible and always test after merges.
8️⃣ One-command migration (Fish shell)
If your repository has no stable release history yet, this command block moves current main into development and resets main to a clean start.
begin
git fetch origin
and git checkout main
and git pull origin main
and git checkout -B development
and git push -u origin development
and git checkout --orphan main-empty
and git rm -rf . >/dev/null 2>&1
and printf "# %s\n" (basename "$PWD") > README.md
and git add README.md
and git commit -m "chore: reset main to clean start"
and git branch -M main
and git push -f origin main
end
Safety notes:
git push -f origin mainrewrites remotemainhistory.- Anyone who already cloned must resync local
main:
git fetch origin
git checkout main
git reset --hard origin/main