Software development is a team sport. Git’s collaboration features — remotes, Pull Requests, and code review — enable multiple developers to work on the same codebase without stepping on each other.

Remotes

A remote is a version of your repository hosted elsewhere (GitHub, GitLab, etc.).

  # View configured remotes
git remote -v
# origin  https://github.com/you/my-app.git (fetch)
# origin  https://github.com/you/my-app.git (push)

# Add a remote
git remote add origin https://github.com/you/my-app.git

# Change remote URL
git remote set-url origin [email protected]:you/my-app.git

# Remove a remote
git remote remove origin
  

Push and Pull

  # Push current branch to origin
git push origin main

# Push and set upstream tracking
git push -u origin feature/login

# After upstream is set
git push    # pushes to tracked remote branch

# Pull latest changes (fetch + merge)
git pull origin main

# Fetch without merging
git fetch origin
git log origin/main..HEAD   # commits you have that remote doesn't
  

SSH vs HTTPS Authentication

HTTPS — username + personal access token:

  git clone https://github.com/you/my-app.git
# Prompts for username and token
  

SSH — key-based, no password prompts:

  ssh-keygen -t ed25519 -C "[email protected]"
cat ~/.ssh/id_ed25519.pub
# Add public key to GitHub → Settings → SSH Keys

git clone [email protected]:you/my-app.git
  

SSH is preferred for daily development.

Fork and Contribute (Open Source)

  your-fork (origin)  →  Pull Request  →  upstream (original repo)
  
  # Fork on GitHub, then clone your fork
git clone [email protected]:yourname/project.git
cd project

# Add upstream remote
git remote add upstream [email protected]:original/project.git

# Keep fork synced
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
  

Pull Requests (PRs)

A Pull Request proposes merging your branch into another (usually main):

  1. Push your feature branch
  2. Open PR on GitHub/GitLab
  3. CI runs automated tests
  4. Teammates review code
  5. Address feedback with new commits
  6. Merge when approved

Good PR Practices

  • Small and focused — one feature or fix per PR
  • Descriptive title — “Add email verification to signup flow”
  • Summary in description — what, why, how to test
  • Link issues — “Closes #42”
  • Self-review first — read your own diff before requesting review

Example PR description:

  ## Summary
- Add email verification step after user registration
- Send verification link via SendGrid
- Block login until email confirmed

## Test plan
- [ ] Register new user → receive email
- [ ] Click verification link → account activated
- [ ] Login before verification → 403 error

Closes #42
  

Code Review Guidelines

As author:

  • Keep PRs under 400 lines when possible
  • Respond to every comment — resolve or explain
  • Don’t take feedback personally

As reviewer:

  • Review within 24 hours
  • Ask questions, don’t just demand changes
  • Approve when satisfied — don’t nitpick style if linter handles it

Common review comments:

  // ❌ Reviewer: Missing error handling
async function getUser(id) {
  const res = await fetch(`/api/users/${id}`);
  return res.json();  // What if 404? Network error?
}

// ✅ Fixed
async function getUser(id) {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error(`User ${id} not found: ${res.status}`);
  return res.json();
}
  

Protected Branches

Configure on GitHub: Settings → Branches → Branch protection rules

Common rules for main:

  • Require Pull Request before merging
  • Require 1+ approving reviews
  • Require status checks (CI) to pass
  • Require branches to be up to date
  • No force push
  • No direct commits
  # This will be rejected on protected main
git push origin main
# remote: error: GH006: Protected branch update failed
  

Handling Review Feedback

  # Make changes on same branch
git add src/auth.js
git commit -m "Address review: add error handling for 404"
git push origin feature/email-verification
# PR updates automatically
  

Merge Strategies

Strategy Result
Merge commit Preserves full branch history
Squash and merge All commits → one commit on main
Rebase and merge Linear history, no merge commit

Squash is popular for feature branches with messy WIP commits.

Resolving Conflicts in PRs

When main moved forward while your PR was open:

  git checkout feature/my-branch
git fetch origin
git rebase origin/main
# Resolve conflicts
git add .
git rebase --continue
git push --force-with-lease origin feature/my-branch
  

--force-with-lease is safer than --force — fails if someone else pushed to your branch.

Team Conventions

Document in CONTRIBUTING.md:

  ## Branch Naming
- feature/short-description
- fix/issue-number-description
- chore/update-dependencies

## Commit Messages
Follow Conventional Commits: feat:, fix:, docs:, chore:

## PR Process
1. Create branch from main
2. Open draft PR early for visibility
3. Request review from @team/frontend
4. Squash merge after approval
  

What Comes Next

With Git collaboration mastered, move to Docker for containerization and CI/CD to automate testing and deployment on every Pull Request.