Ready to collaborate like a professional development team? After mastering Git branching and remote management, it's time to learn industry-standard workflows that teams use every day. This tutorial follows a real terminal session demonstrating Git Flow, pull requests, code reviews, and team collaboration on GitHub.
šÆ What You'll Learn: In this comprehensive guide, you'll discover:
- Understanding Git Flow workflow and why teams use it
- Setting up a collaborative repository structure
- Creating and managing development branches (main, dev, feature branches)
- Understanding the difference between 'main' and 'master' branch naming
- Making changes on feature branches
- Creating pull requests for code review
- Reviewing and merging pull requests on GitHub
- Understanding pull request approval workflows
- Closing and reopening pull requests
- Merging through multiple branch levels (feature ā dev ā main)
- Adding collaborators to GitHub repositories
- Setting up branch protection rules
- Best practices for team-based Git workflows
Prerequisites: Understanding of Git branching and a GitHub account
š Introduction to Git Workflows
What is Git Flow?
Git Flow: A branching model designed for professional development teams that provides a robust framework for managing releases, features, and hotfixes.
Real-World Analogy: Think of Git Flow like a manufacturing pipeline:
- Main/Master Branch: The finished products ready for customers (production)
- Dev Branch: The assembly line where features come together (staging)
- Feature Branches: Individual workstations where specific components are built (development)
Key Benefits:
- ā Organized Development: Clear structure for where different types of work happen
- ā Stable Production: Main branch always contains stable, tested code
- ā Parallel Development: Multiple features can be developed simultaneously
- ā Code Review: Changes are reviewed before merging
- ā Easy Rollback: Issues can be isolated and reverted easily
Git Flow Branch Structure
| Branch Type | Purpose | Lifespan |
|---|---|---|
| main/master | Production-ready code | Permanent |
| dev/develop | Integration branch for features | Permanent |
| feature/* | New features being developed | Temporary (until merged) |
| release/* | Preparing for production release | Temporary (until released) |
| hotfix/* | Emergency fixes for production | Temporary (until fixed) |
šļø Setting Up a Git Flow Repository
Creating the Repository on GitHub
Let's start fresh with a new repository specifically for demonstrating Git Flow:
Steps Performed (as shown in the terminal session comments):
- Go to GitHub and create a new repository
- Repository name: "demo-git-flow"
- Add a description (optional but recommended)
- Set visibility to Public
- Initialize with a README - This time we DO want this
- Click "Create repository"
š” Why Initialize with README?: For Git Flow demos, starting with a README creates an initial commit on the main branch, giving us a proper starting point for our workflow.
Cloning the Repository
[03:16:08 centos9@vbox Repo]$ git clone https://github.com/owais-io/demo-git-flow.git
Cloning into 'demo-git-flow'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.
[03:18:41 centos9@vbox Repo]$ cd demo-git-flow/
Clone Output Analysis:
- remote: Enumerating objects: 3 - GitHub sends initial files
- Receiving objects: 100% - Successfully downloaded
- Result: Full repository with README.md and all Git infrastructure
Verifying Repository Contents
[03:18:50 centos9@vbox demo-git-flow]$ ls
README.md
[03:18:51 centos9@vbox demo-git-flow]$ ls -al
total 4
drwxr-xr-x. 3 centos9 centos9 35 Oct 19 03:18 .
drwxr-xr-x. 6 centos9 centos9 97 Oct 19 03:18 ..
drwxr-xr-x. 8 centos9 centos9 163 Oct 19 03:18 .git
-rw-r--r--. 1 centos9 centos9 30 Oct 19 03:18 README.md
Directory Contents:
- README.md - Initial project file
- .git/ - Git repository metadata (163 bytes of infrastructure)
- Ready to work: Full Git repository cloned and functional
š Creating Initial Commits on Main Branch
Understanding Main vs Master
The terminal session shows we're on the main branch (not master):
[03:19:53 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
first.txt
nothing added to commit but untracked files present (use "git add" to track)
Main vs Master - Important Context:
Historical Background:
- Older Git versions used "master" as the default branch name
- In 2020, GitHub changed the default to "main" for new repositories
- Existing repositories can keep using "master" or rename to "main"
Why the Change? The tech community moved toward more inclusive language. "Main" better represents the branch's purpose (the main line of development) without historical baggage.
What This Means for You:
- New GitHub repos: Default to "main"
- Older repos: May still use "master"
- Functionally identical: Both serve the same purpose
- Commands work the same: Just use the appropriate name for your repo
How to Check Your Default:
git branch --show-current
Adding Files to Main Branch
Let's create some initial content:
[03:18:57 centos9@vbox demo-git-flow]$ vim first.txt
[03:19:51 centos9@vbox demo-git-flow]$ cat first.txt
This is first change
[03:19:53 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
first.txt
nothing added to commit but untracked files present (use "git add" to track)
File Creation:
- Created
first.txtwith content: "This is first change" - File is untracked (Git sees it but isn't tracking changes)
Attempting to Commit Without Staging
This demonstrates a common beginner mistake:
[03:19:59 centos9@vbox demo-git-flow]$ git commit -m "added first.txt"
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
first.txt
nothing added to commit but untracked files present (use "git add" to track)
Why This Failed:
- Untracked files aren't automatically staged: Must use
git addfirst - Git's helpful error: Shows exactly what needs to be done
- Two-step process: Add ā Commit (always in this order)
Correct Workflow: Stage Then Commit
[03:20:13 centos9@vbox demo-git-flow]$ git add .
[03:20:32 centos9@vbox demo-git-flow]$ git commit -m "added first.txt"
[main 60c5cf3] added first.txt
1 file changed, 1 insertion(+)
create mode 100644 first.txt
[03:20:35 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
Success Indicators:
- [main 60c5cf3] - Committed on main branch with hash 60c5cf3
- 1 file changed, 1 insertion(+) - Added one file with one line
- Ahead by 1 commit - Local main has changes remote doesn't have
Adding Second File
Let's add one more file to main:
[03:20:38 centos9@vbox demo-git-flow]$ vim second.txt
[03:21:10 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
second.txt
nothing added to commit but untracked files present (use "git add" to track)
[03:21:14 centos9@vbox demo-git-flow]$ git add .
[03:21:18 centos9@vbox demo-git-flow]$ git commit -m "added second.txt"
[main c3cffdf] added second.txt
1 file changed, 1 insertion(+)
create mode 100644 second.txt
[03:21:30 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
Status Changes:
- Ahead by 2 commits - Two local commits not yet pushed to GitHub
- Both first.txt and second.txt are now committed
Pushing to GitHub
[03:21:51 centos9@vbox demo-git-flow]$ git push
Username for 'https://github.com': owais-io
Password for 'https://owais-io@github.com':
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 536 bytes | 536.00 KiB/s, done.
Total 6 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/owais-io/demo-git-flow.git
fafe251..c3cffdf main -> main
[03:22:09 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
Push Success:
- Total 6 objects - All our changes sent to GitHub
- fafe251..c3cffdf - Commit range updated
- Up to date - Local and remote now synchronized
šæ Creating Branch Structure on GitHub
Creating the Dev Branch
Now let's create our development integration branch directly on GitHub:
Steps to Create Dev Branch on GitHub:
- Navigate to your repository on GitHub
- Click the branch dropdown (currently showing "main")
- Type "dev" in the search box
- Click "Create branch: dev from 'main'"
- The dev branch is now created, identical to main
š” Why Create on GitHub?: Creating branches on GitHub is useful when setting up repository structure before developers start working. It ensures everyone has access to the branches immediately.
Creating Developer Feature Branches
Following Git Flow, each developer should have their own feature branch created from dev:
Steps to Create dev-owais Branch:
- Switch to the dev branch on GitHub (using the branch dropdown)
- Type "dev-owais" in the branch search box
- Click "Create branch: dev-owais from 'dev'"
- Feature branch created for developer "owais"
Branch Naming Convention:
- Pattern:
dev-<developer-name>orfeature/<feature-name> - Purpose: Clearly identifies who is working on what
- Examples: dev-owais, dev-sarah, feature/login, feature/payment
š„ Pulling Remote Branches Locally
Detecting New Branches
Let's pull the branches we created on GitHub:
[03:28:07 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
[03:28:10 centos9@vbox demo-git-flow]$ git branch
* main
[03:28:23 centos9@vbox demo-git-flow]$ git pull
From https://github.com/owais-io/demo-git-flow
* [new branch] dev -> origin/dev
* [new branch] dev-owais -> origin/dev-owais
Already up to date.
[03:28:41 centos9@vbox demo-git-flow]$ git branch
* main
Pull Output Analysis:
- [new branch] dev -> origin/dev - Git discovered the dev branch
- [new branch] dev-owais -> origin/dev-owais - Git discovered the feature branch
- Already up to date - Main branch has no new commits
- Local branches: Still only shows main
Important Understanding: Git now knows about the remote branches (they're in the remote tracking refs) but hasn't created local branches for them yet.
Switching to Feature Branch
Let's check out the dev-owais branch:
[03:28:47 centos9@vbox demo-git-flow]$ git checkout dev-owais
branch 'dev-owais' set up to track 'origin/dev-owais'.
Switched to a new branch 'dev-owais'
[03:28:58 centos9@vbox demo-git-flow]$ git branch
* dev-owais
main
[03:29:00 centos9@vbox demo-git-flow]$ git status
On branch dev-owais
Your branch is up to date with 'origin/dev-owais'.
nothing to commit, working tree clean
Checkout Magic:
- Automatic local branch creation: Git created dev-owais locally
- Automatic tracking setup: Linked to origin/dev-owais
- Switched to new branch: Now working on dev-owais
š» Working on Feature Branch
Adding Feature Content
Let's add a new feature to our dev-owais branch:
[03:29:00 centos9@vbox demo-git-flow]$ vim third.txt
[03:29:27 centos9@vbox demo-git-flow]$ git add .
[03:29:30 centos9@vbox demo-git-flow]$ git commit -m "added third.txt"
[dev-owais eda1bb6] added third.txt
1 file changed, 1 insertion(+)
create mode 100644 third.txt
[03:29:42 centos9@vbox demo-git-flow]$ git push
Username for 'https://github.com': owais-io
Password for 'https://owais-io@github.com':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 297 bytes | 297.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/owais-io/demo-git-flow.git
c3cffdf..eda1bb6 dev-owais -> dev-owais
First Feature Commit:
- Created third.txt with content: "hello this is third file"
- Committed on dev-owais branch
- Pushed to GitHub successfully
Modifying Existing Files
Let's make another change:
[03:30:10 centos9@vbox demo-git-flow]$ vim second.txt
[03:30:39 centos9@vbox demo-git-flow]$ cat second.txt
this is second chang
hello updated second.txt
[03:30:41 centos9@vbox demo-git-flow]$ git add .
[03:30:51 centos9@vbox demo-git-flow]$ git commit -m "appended second.txt"
[dev-owais 4356c25] appended second.txt
1 file changed, 3 insertions(+), 1 deletion(-)
[03:31:04 centos9@vbox demo-git-flow]$ git status
On branch dev-owais
Your branch is ahead of 'origin/dev-owais' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
[03:31:08 centos9@vbox demo-git-flow]$ git push
Username for 'https://github.com': owais-io
Password for 'https://owais-io@github.com':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/owais-io/demo-git-flow.git
eda1bb6..4356c25 dev-owais -> dev-owais
Second Feature Commit:
- Modified second.txt (appended new content)
- 3 insertions, 1 deletion - Shows line changes
- Successfully pushed to remote
Verifying Branch Isolation
Let's verify that changes are isolated to dev-owais:
[03:31:34 centos9@vbox demo-git-flow]$ git checkout master
error: pathspec 'master' did not match any file(s) known to git
[03:31:40 centos9@vbox demo-git-flow]$ ls
first.txt README.md second.txt third.txt
[03:31:47 centos9@vbox demo-git-flow]$ cat second.txt
this is second chang
hello updated second.txt
[03:31:47 centos9@vbox demo-git-flow]$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
[03:32:07 centos9@vbox demo-git-flow]$ ls
first.txt README.md second.txt
[03:32:08 centos9@vbox demo-git-flow]$ cat second.txt
this is second change
Branch Isolation Confirmed:
- Error with 'master': This repo uses 'main' (not master)
- On dev-owais: 3 files (third.txt exists), modified second.txt
- On main: 2 files (third.txt doesn't exist), original second.txt
- Perfect isolation: Changes on dev-owais don't affect main
š Understanding Pull Requests
What is a Pull Request?
Pull Request (PR): A GitHub feature that lets you tell others about changes you've pushed to a branch. It's a request to merge your code into another branch, with a review and approval process.
Real-World Analogy: Think of a pull request like submitting an assignment for review:
- You complete your work (commits on feature branch)
- You submit it for review (create pull request)
- Teacher reviews it (code review by team lead/peers)
- Teacher can approve, request changes, or reject (merge, comment, or close)
- Once approved, it goes into the grade book (merged into target branch)
Key Components:
- ā Source Branch: Where your changes are (dev-owais)
- ā Target Branch: Where you want changes to go (dev)
- ā Description: Explanation of what changed and why
- ā Review Process: Team can comment, approve, or request changes
- ā Merge Decision: Accept or reject the changes
Creating Your First Pull Request
Steps to Create a Pull Request on GitHub:
- Go to your GitHub repository
- Click on the "Pull requests" tab
- Click "New pull request" button
- Select base branch:
dev(where you want changes to go) - Select compare branch:
dev-owais(your feature branch with changes) - Review the changes shown in green (you'll see "Able to merge" if no conflicts)
- Click "Create pull request"
- Add a meaningful title: "Dev-owais request pull to be merged in dev branch"
- Add a description explaining your changes
- (Optional) Assign reviewers from your team
- Click "Create pull request"
What GitHub Shows:
Able to merge
These branches can be automatically merged.
This green message means:
- No merge conflicts exist
- Changes can be integrated automatically
- Safe to proceed with the merge
š„ Pull Request Review Process
Reviewing Pull Requests
When you (or a team lead) reviews a pull request, you can see:
- Files changed: Which files were modified
- Commits: All commits included in the pull request
- Diff view: Line-by-line comparison of changes
Review Options:
- Merge pull request - Accept and integrate the changes
- Comment - Ask questions or provide feedback
- Close pull request - Reject without merging
- Request changes - Ask for modifications before accepting
Closing a Pull Request (Without Merging)
In our demonstration, the reviewer closes the first pull request:
Steps Shown in Terminal Comments:
- Navigate to the pull request
- Scroll down to find "Close pull request" button
- Add a comment explaining why: "cannot merge"
- Click "Comment" to submit
- Click "Close pull request"
- Status changes to "Closed" (not merged)
Why Close Without Merging?
- Code needs significant changes
- Feature no longer needed
- Conflicts with other work
- Quality standards not met
Reopening and Creating New Pull Request
The session shows creating a second pull request:
Steps:
- Click "New pull request" again
- Select base:
dev, compare:dev-owais(same as before) - Create the pull request with title and description
- This time, it will be approved
Result: Now there are 2 pull requests visible:
- 1 Open (the new one)
- 1 Closed (the rejected one)
This demonstrates that pull request history is preserved on GitHub.
ā Merging Pull Requests
Approving and Merging
The session demonstrates the approval process:
# Terminal comment indicates:
# this time click on "merge pull request" and "confirm merge"
Steps to Merge Pull Request:
- Review all changes one final time
- Click "Merge pull request" button
- (Optional) Edit the merge commit message
- Click "Confirm merge" button
- Pull request status changes to "Merged"
- The purple merged icon appears
- Changes are now in the dev branch!
Post-Merge State on GitHub:
- main branch: 2 files (first.txt, second.txt)
- dev branch: 3 files (first.txt, second.txt, third.txt) + modifications
- dev-owais branch: 3 files (same as dev now)
Creating Second-Level Pull Request
Following Git Flow, dev branch changes should eventually go to main:
Steps for Dev ā Main Pull Request:
- Create a new pull request
- Select base:
main, compare:dev - Title: "merge dev to main branch"
- Review all changes (will include everything from dev-owais)
- Click "Create pull request"
- Review and click "Merge pull request"
- Click "Confirm merge"
Result: Main branch now has all the changes from dev (which included dev-owais changes).
This demonstrates the Git Flow hierarchy:
feature branch (dev-owais)
ā Pull Request #1 (merged)
dev branch
ā Pull Request #2 (merged)
main branch
š Synchronizing Local Repository
Checking Local Status
After merging on GitHub, local repository is out of sync:
[04:09:26 centos9@vbox demo-git-flow]$ git status
On branch dev-owais
Your branch is up to date with 'origin/dev-owais'.
nothing to commit, working tree clean
[04:09:55 centos9@vbox demo-git-flow]$ git log
commit 4356c25e2e3a6ffb62da773157988dbc126f8b22 (HEAD -> dev-owais, origin/dev-owais)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 03:31:04 2025 +0500
appended second.txt
commit eda1bb64b0f1c0a8a799fdc42a93c78c68348a91
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 03:29:42 2025 +0500
added third.txt
commit c3cffdf1622d03b33329f1c0dfef98f74ef326f2 (origin/main, origin/dev, origin/HEAD, main)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 03:21:30 2025 +0500
added second.txt
[... previous commits ...]
What We See:
- origin/main and origin/dev point to the same old commit (c3cffdf)
- Local doesn't know about the merges that happened on GitHub
- Need to pull to synchronize
Pulling Merge Commits
[04:09:59 centos9@vbox demo-git-flow]$ git pull
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (2/2), 1.76 KiB | 1.76 MiB/s, done.
From https://github.com/owais-io/demo-git-flow
c3cffdf..65cf187 dev -> origin/dev
c3cffdf..a5928c5 main -> origin/main
Already up to date.
Pull Output Analysis:
- c3cffdf..65cf187 dev -> origin/dev - Dev branch updated with merge commit
- c3cffdf..a5928c5 main -> origin/main - Main branch updated with merge commit
- Already up to date: dev-owais hasn't changed (we're already on latest)
Important: Git updated the remote tracking refs but didn't update our local dev and main branches yet.
Updating Local Main Branch
[04:10:40 centos9@vbox demo-git-flow]$ git checkout main
Switched to branch 'main'
Your branch is behind 'origin/main' by 4 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
[04:10:54 centos9@vbox demo-git-flow]$ git pull
Updating c3cffdf..a5928c5
Fast-forward
second.txt | 4 +++-
third.txt | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
create mode 100644 third.txt
[04:10:57 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
Sync Success:
- Behind by 4 commits - Git detected missing commits
- Fast-forward - Clean merge of remote changes
- 2 files changed - third.txt added, second.txt modified
- Now up to date - Local main matches GitHub
Examining Merge Commits in History
[04:11:00 centos9@vbox demo-git-flow]$ git log
commit a5928c59a7b792eff60e2591056b021bb68ea634 (HEAD -> main, origin/main, origin/HEAD)
Merge: c3cffdf 65cf187
Author: Owais Abbasi <81351747+owais-io@users.noreply.github.com>
Date: Sun Oct 19 04:08:42 2025 +0500
Merge pull request #3 from owais-io/dev
merge dev to main branch
commit 65cf18761d71dd0f50a2b3fbaae993d9bde76ffb (origin/dev)
Merge: c3cffdf 4356c25
Author: Owais Abbasi <81351747+owais-io@users.noreply.github.com>
Date: Sun Oct 19 04:04:01 2025 +0500
Merge pull request #2 from owais-io/dev-owais
Dev-owais request pull to be merged in dev branch
commit 4356c25e2e3a6ffb62da773157988dbc126f8b22 (origin/dev-owais, dev-owais)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 03:31:04 2025 +0500
appended second.txt
commit eda1bb64b0f1c0a8a799fdc42a93c78c68348a91
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 03:29:42 2025 +0500
added third.txt
[... previous commits ...]
Understanding Merge Commits:
- Merge commit a5928c5: Pull request #3 (dev ā main)
- Merge commit 65cf187: Pull request #2 (dev-owais ā dev)
- Regular commits: Feature work (4356c25, eda1bb6)
- Merge references: Show which pull requests created these merges
Visual Representation:
a5928c5 (main) ā Merge PR #3 (dev ā main)
āā c3cffdf (original main)
āā 65cf187 (dev) ā Merge PR #2 (dev-owais ā dev)
āā c3cffdf (original dev)
āā 4356c25 (dev-owais) ā "appended second.txt"
āā eda1bb6 ā "added third.txt"
āā c3cffdf (base)
Updating Local Dev Branch
[04:11:02 centos9@vbox demo-git-flow]$ git checkout dev
branch 'dev' set up to track 'origin/dev'.
Switched to a new branch 'dev'
[04:11:20 centos9@vbox demo-git-flow]$ git pull
Already up to date.
[04:11:28 centos9@vbox demo-git-flow]$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
Dev Branch Sync:
- Created local dev branch: Checked out from remote
- Automatic tracking: Set up to track origin/dev
- Already up to date: No new changes to pull
Verifying All Branches
[04:12:00 centos9@vbox demo-git-flow]$ ls
first.txt README.md second.txt third.txt
[04:12:03 centos9@vbox demo-git-flow]$ git branch
* dev
dev-owais
main
[04:12:08 centos9@vbox demo-git-flow]$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
[04:12:14 centos9@vbox demo-git-flow]$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
[04:12:15 centos9@vbox demo-git-flow]$ ls
first.txt README.md second.txt third.txt
[04:12:23 centos9@vbox demo-git-flow]$ cat second.txt
this is second chang
hello updated second.txt
[04:12:25 centos9@vbox demo-git-flow]$ cat third.txt
hello this is third file
Final State:
- All branches in sync: main, dev, and dev-owais all updated
- All files present: first.txt, second.txt, third.txt, README.md
- Changes merged: Modifications from dev-owais now in main
- Complete workflow: Feature ā Dev ā Main successfully completed
š„ Adding Collaborators
How to Add Collaborators to GitHub Repository
The session mentions adding collaborators to enable team collaboration:
Steps to Add Collaborators:
- Go to your GitHub repository
- Click "Settings" tab
- Click "Collaborators" in the left sidebar (under "Access")
- Click "Add people" button
- Enter the GitHub username or email of your collaborator
- Select the correct user from the search results
- Choose their permission level:
- Read: View and clone
- Write: Read + create branches and pull requests
- Admin: Write + manage settings
Invitation Process:
- Collaborator receives an email notification
- They can accept or decline the invitation
- You can also copy an invitation link to send directly
After Acceptance:
- Collaborator can clone the repository
- They can create branches and push commits
- They can create pull requests
- Depending on permissions, they may be able to merge PRs
š” Best Practice: Add team members as collaborators with Write access. Reserve Admin access for project leads who need to manage repository settings.
š”ļø Branch Protection Rules
Understanding Branch Protection
The session mentions branch protection rules in the comments:
# Settings >> Branches >> Branch protection rules
# you can also add rules. explain it in detail and how to do it.
Branch Protection Rules: GitHub features that protect important branches from accidental or unauthorized changes.
Why Branch Protection Matters:
- š”ļø Prevent accidental deletions: Can't delete protected branches
- š”ļø Require code reviews: Force pull request reviews before merging
- š”ļø Enforce status checks: Ensure tests pass before merging
- š”ļø Maintain code quality: Prevent direct pushes to main/production
- š”ļø Control who can merge: Restrict merge permissions
Setting Up Branch Protection Rules
Steps to Configure Branch Protection:
-
Navigate to Settings:
- Go to your repository on GitHub
- Click "Settings" tab
- Click "Branches" in the left sidebar
-
Create Protection Rule:
- Click "Add branch protection rule" button
- Enter branch name pattern:
main(or use wildcards likerelease/*)
-
Configure Protection Settings:
| Rule | What It Does | When to Use |
|---|---|---|
| Require pull request reviews | Code must be reviewed before merging | Always for main/production branches |
| Required approvals | Specify number of approvals needed (1-6) | 1-2 for small teams, 2+ for larger teams |
| Dismiss stale reviews | Re-approval needed if code changes | Ensures reviews are current |
| Require status checks | Tests/CI must pass before merging | When you have automated testing |
| Require branches to be up to date | Branch must be current with base | Prevent integration issues |
| Require linear history | No merge commits allowed | When you want clean, linear history |
| Include administrators | Rules apply even to admins | Maximum protection |
| Restrict who can push | Only specific people/teams can push | Highly controlled environments |
| Allow force pushes | Permit git push --force | Generally should be disabled |
| Allow deletions | Permit branch deletion | Should be disabled for main/prod |
- Save Protection Rule:
- Click "Create" or "Save changes" button
- Rules are immediately enforced
Recommended Protection Settings
For Main/Production Branch:
ā
Require pull request reviews (1-2 approvals)
ā
Require status checks to pass
ā
Require branches to be up to date
ā
Include administrators (enforce for everyone)
ā
Restrict who can push (optional, for high-security)
ā Allow force pushes (dangerous!)
ā Allow deletions (protect the branch)
For Dev/Staging Branch:
ā
Require pull request reviews (1 approval)
ā
Require status checks to pass
ā
Require branches to be up to date
ā ļø Include administrators (optional)
ā Allow force pushes (generally avoid)
ā ļø Allow deletions (maybe for cleanup)
For Feature Branches:
ā ļø Usually no protection needed (temporary branches)
ā
Delete after merging (keep repository clean)
Testing Branch Protection
Once rules are set up, try to push directly to main:
# This will now fail if protection is enabled
git checkout main
echo "test" >> file.txt
git add .
git commit -m "direct commit"
git push origin main
# Error: Cannot push to protected branch
Expected Error:
remote: error: GH006: Protected branch update failed
remote: error: Required status check "tests" is expected
remote: error: At least 1 approving review is required
This forces developers to use the pull request workflow!
šÆ Best Practices for Team Collaboration
Git Flow Workflow Best Practices
| Practice | Why Important | How To Implement |
|---|---|---|
| Always Work on Feature Branches | Isolates changes, enables parallel work | Create branch from dev, never commit directly to main |
| Write Clear Pull Request Descriptions | Helps reviewers understand changes | Explain what, why, and how to test |
| Keep Pull Requests Small | Easier to review, faster to merge | Aim for 200-400 lines changed per PR |
| Review Code Thoroughly | Catches bugs early, shares knowledge | Check logic, style, tests, edge cases |
| Delete Merged Branches | Keeps repository clean | GitHub offers "Delete branch" after merge |
| Sync Regularly | Avoid large merge conflicts | Pull from dev daily, rebase feature branches |
| Use Branch Protection | Prevents mistakes on critical branches | Protect main and dev branches always |
Pull Request Review Best Practices
| Do | Don't |
|---|---|
| ā Review within 24 hours | ā Let PRs sit for days |
| ā Ask questions politely | ā Be rude or dismissive |
| ā Explain your reasoning | ā Just say "change this" |
| ā Praise good code | ā Only point out problems |
| ā Suggest alternatives | ā Demand specific solutions |
| ā Test the changes if possible | ā Approve without understanding |
š Git Workflow Commands Cheat Sheet
Pull Request Workflow Commands
# 1. Start with fresh dev branch
git checkout dev
git pull origin dev
# 2. Create feature branch from dev
git checkout -b feature/my-feature
# 3. Make changes and commit
# (edit files)
git add .
git commit -m "Add feature X"
# 4. Push feature branch to GitHub
git push -u origin feature/my-feature
# 5. Create pull request on GitHub (via web interface)
# - Base: dev
# - Compare: feature/my-feature
# 6. After PR is approved and merged on GitHub
# 7. Update local dev branch
git checkout dev
git pull origin dev
# 8. Delete feature branch (locally)
git branch -d feature/my-feature
# 9. Delete feature branch (remote)
git push origin --delete feature/my-feature
Branch Management Commands
# View all branches (local and remote)
git branch -a
# View only remote branches
git branch -r
# View branches with last commit info
git branch -v
# View merged branches
git branch --merged
# View unmerged branches
git branch --no-merged
# Switch to existing branch
git checkout branch-name
# Create and switch to new branch
git checkout -b new-branch-name
# Create branch from specific commit
git checkout -b new-branch commit-hash
# Rename current branch
git branch -m new-name
# Delete local branch (safe)
git branch -d branch-name
# Delete local branch (force)
git branch -D branch-name
# Delete remote branch
git push origin --delete branch-name
Synchronization Commands
# Fetch all remote changes (doesn't merge)
git fetch origin
# Fetch and prune deleted remote branches
git fetch origin --prune
# Pull changes from remote
git pull origin branch-name
# Pull with rebase instead of merge
git pull --rebase origin branch-name
# Push local branch to remote
git push origin branch-name
# Push with upstream tracking
git push -u origin branch-name
# Push all branches
git push origin --all
# See what would be pushed
git log origin/branch-name..HEAD
# See what would be pulled
git log HEAD..origin/branch-name
Collaboration Commands
# View remote repositories
git remote -v
# Add collaborator's fork as remote
git remote add collaborator https://github.com/user/repo.git
# Fetch from collaborator's fork
git fetch collaborator
# Merge collaborator's branch
git merge collaborator/branch-name
# View contributors
git shortlog -sn
# View specific author's commits
git log --author="Author Name"
# View file history
git log --follow filename
šÆ Key Takeaways
ā Git Workflow Concepts Mastered
-
Git Flow Structure: Understood the hierarchy of main ā dev ā feature branches
-
Main vs Master: Learned about the naming convention change and why it happened
-
Repository Setup: Created a collaborative repository with proper branch structure
-
Pull Requests: Mastered creating, reviewing, and merging pull requests on GitHub
-
Code Review Process: Understood the approval workflow and closing/reopening PRs
-
Multi-Level Merging: Successfully merged through feature ā dev ā main hierarchy
-
Local Synchronization: Pulled merge commits and updated all local branches
-
Team Collaboration: Learned to add collaborators and manage permissions
-
Branch Protection: Understood how to protect critical branches with rules
-
Professional Workflow: Applied industry-standard practices for team development
š What's Next?
Now that you've mastered Git Flow and pull requests, consider exploring:
- Advanced Merging: Handling complex merge conflicts
- Git Rebase: Alternative to merging for cleaner history
- GitHub Actions: Automating tests and deployments
- Git Hooks: Running scripts on Git events
- Monorepo Strategies: Managing multiple projects in one repository
š Congratulations! You've successfully mastered:
- ā Git Flow workflow and branch hierarchy
- ā Creating and managing pull requests on GitHub
- ā Understanding main vs master branch naming
- ā Code review and approval processes
- ā Multi-level branch merging (feature ā dev ā main)
- ā Adding collaborators to repositories
- ā Setting up branch protection rules
- ā Professional team collaboration workflows
You're now ready for real-world team development! You have all the skills needed to contribute to professional software projects using industry-standard Git workflows.
š¬ Discussion
How is your team collaboration experience going?
- Have you created pull requests for your projects?
- What's your experience with code reviews?
- Have you set up branch protection rules?
- Are you using Git Flow or a different workflow?
- What challenges have you faced with team collaboration?
- How do you handle merge conflicts in pull requests?
