6  Collaboration with GitHub

Git tracks your project’s history on your local machine. GitHub takes this further by hosting your repository in the cloud, enabling collaboration with teammates, providing tools for code review, and serving as a backup for your work. In professional environments, GitHub (or similar platforms) is where engineering teams coordinate their efforts.

This chapter introduces GitHub as a collaboration platform. You’ll learn to synchronize local and remote repositories, contribute to team projects, and use GitHub’s project management features. By the end, you’ll have a complete workflow for contributing to collaborative engineering projects.

6.1 Git is Distributed

Before diving into GitHub, you need to understand a key concept: Git is a distributed version control system. Every person who clones a repository gets a complete copy, including the entire history. There is no single “master” copy that everyone depends on. Your local repository is just as complete as anyone else’s.

This distributed nature provides resilience. If GitHub went offline tomorrow, every collaborator would still have the complete project history on their machine. Work can continue offline, and repositories can be synchronized when connectivity returns.

However, distributed systems need a way to coordinate. If ten engineers each have complete repositories on their laptops, how do they share changes? This is where GitHub fits in. It hosts a remote repository that serves as a coordination point. Everyone pushes their changes to GitHub and pulls others’ changes from it. GitHub isn’t technically “the source of truth” in Git’s architecture, but teams treat it as a central hub where the official version lives.

6.2 Remote Repositories

A remote is a Git repository hosted somewhere other than your local machine. You can have multiple remotes, but most workflows use a single remote called origin that points to GitHub.

6.2.1 Cloning an Existing Repository

The most common way to start working with a GitHub repository is to clone it. Cloning downloads the complete repository, including all files and history, to your local machine:

terminal
git clone https://github.com/username/project-name.git

This creates a new directory called project-name containing the repository. Git automatically configures the remote origin to point back to GitHub.

Move into the cloned directory:

terminal
cd project-name

Verify the remote configuration:

terminal
git remote -v
output
origin  https://github.com/username/project-name.git (fetch)
origin  https://github.com/username/project-name.git (push)

6.2.2 Connecting a Local Repository to GitHub

If you have an existing local repository (created with git init as described in Chapter 5) and want to push it to GitHub, first create a new repository on GitHub (without initializing it with any files). Then connect your local repository:

terminal
git remote add origin https://github.com/username/your-repo.git

Verify the connection:

terminal
git remote -v

Now your local repository knows where to push changes.

6.3 Pushing and Pulling

Synchronizing changes between your local repository and GitHub involves two operations: push sends your commits to GitHub, and pull downloads commits from GitHub to your machine.

6.3.1 Pushing Changes

After making commits locally, push them to GitHub:

terminal
git push origin main

This command says “push the commits from my local main branch to the origin remote’s main branch.”

The first time you push a new branch, you may need to set up tracking:

terminal
git push -u origin main

The -u flag establishes a tracking relationship. After this, you can simply use git push without specifying the remote and branch.

6.3.2 Pulling Changes

When collaborators push their commits to GitHub, you need to pull those changes to stay synchronized:

terminal
git pull origin main

Or simply, if tracking is established:

terminal
git pull

git pull actually does two things: it fetches commits from the remote (downloads them without merging) and then merges them into your current branch. If you want to see what’s new on the remote without merging yet:

terminal
git fetch origin
git log origin/main --oneline

This lets you review incoming changes before integrating them.

You and a teammate are working on the same project with a GitHub remote. You both make commits locally. Your teammate pushes first. When you try to push, Git refuses and says your local branch is “behind” the remote. What does this mean, and what commands do you need to run to resolve it? In what order?

Your teammate’s commits are on GitHub, but your local repository doesn’t have them yet. Your local commits aren’t on GitHub. First, run git pull origin main to fetch their changes and merge them with your local work. Then run git push origin main to send your commits (and the merged state) to GitHub. Pull before push ensures you’re working with the latest version and reduces merge conflicts.

6.3.3 Handling Conflicts

When you and a collaborator modify the same lines of a file, Git cannot automatically merge the changes. This is called a merge conflict. Git marks the conflicting sections in the file:

analyze_sensors.py
def process_reading(value):
<<<<<<< HEAD
    return value * 1.05  # Your change: 5% calibration factor
=======
    return value * 1.03  # Their change: 3% calibration factor
>>>>>>> origin/main

To resolve the conflict, edit the file to keep the correct version (or combine both changes), remove the conflict markers, then stage and commit:

terminal
git add analyze_sensors.py
git commit -m "Resolve calibration factor conflict, use 5%"
TipAvoiding Conflicts

The best way to handle conflicts is to avoid them. Communicate with your team about who’s working on which files. Pull frequently so your local copy stays close to the remote. Make small, focused commits that are easier to merge.

6.4 The Collaborative Workflow

Professional teams follow structured workflows to coordinate contributions. The most common pattern uses feature branches and pull requests.

6.4.1 Feature Branch Workflow

Instead of committing directly to main, you create a branch for each feature or fix:

terminal
git switch -c feature/add-anomaly-detection

Work on the branch, making commits as you go:

terminal
git add anomaly.py
git commit -m "Implement statistical anomaly detection"
git add tests/test_anomaly.py
git commit -m "Add tests for anomaly detection"

Push the branch to GitHub:

terminal
git push -u origin feature/add-anomaly-detection

Now your work is backed up on GitHub, but it hasn’t affected main yet. The next step is to propose merging your branch through a pull request.

6.4.2 Pull Requests

A pull request (PR) is GitHub’s mechanism for proposing that changes from one branch be merged into another. Despite the confusing name (you’re requesting that someone pull your changes), pull requests are really about review and discussion.

When you push a branch to GitHub, you’ll see a prompt to create a pull request. Click it, or navigate to the repository and click “New pull request.” Select your feature branch as the source and main as the destination.

Write a clear title and description explaining what the PR accomplishes, why the changes are needed, and any context reviewers should know. Good PR descriptions save everyone time.

You’ve pushed a feature branch called feature/anomaly-detection to GitHub. You create a pull request to merge it into main. A teammate reviews your code and requests changes. You make those changes locally, commit them, and push to your feature branch. What happens to your pull request? Do you need to create a new PR?

Your pull request automatically updates with the new commits you pushed. The PR doesn’t close; it shows all commits from your feature branch until it’s merged. GitHub shows the conversation history with your teammate’s feedback and your responses. You don’t need to create a new PR. When your teammate approves, you can merge directly from the existing PR.

6.4.3 Code Review

Pull requests enable code review, one of the most valuable practices in software engineering. Reviewers can comment on specific lines, suggest changes, ask questions, and ultimately approve or request changes to the PR.

As a contributor, respond to feedback thoughtfully. If you need to make changes, commit them to your branch and push. The PR automatically updates with your new commits.

As a reviewer, focus on correctness, clarity, and maintainability. Ask questions rather than making demands. Remember that code review is a learning opportunity for everyone involved.

You have a feature branch that’s 5 commits ahead of main. You want to merge it via a pull request. GitHub shows “This branch can be automatically merged.” What does this mean? Under what circumstances would GitHub show “Merge conflict” instead? If a conflict appears, can you still merge, or is the PR blocked?

“This branch can be automatically merged” means no conflicts exist; the same files weren’t changed differently on both branches. A merge conflict appears when you and someone else both modified the same lines of the same file. If conflicts exist, GitHub shows the PR as blocked and requires you to resolve conflicts locally, commit the resolution, and push before merging. Conflicts aren’t failures; they’re Git asking you to decide which version is correct when it can’t determine automatically.

6.4.4 Merging Pull Requests

Once the PR is approved and any automated checks pass, you can merge it. GitHub offers several merge strategies. For most workflows, a simple merge commit works well. Click “Merge pull request” on GitHub.

After merging, delete the feature branch. It’s served its purpose, and keeping old branches around creates clutter:

terminal
git switch main
git pull
git branch -d feature/add-anomaly-detection

6.5 Project Management on GitHub

GitHub provides tools beyond code hosting that help teams coordinate work. These features turn GitHub into a project management platform.

6.5.1 Issues

Issues track tasks, bugs, feature requests, and discussions. Create an issue for anything that needs to be done or decided. Good issues include a clear title, a detailed description of the problem or desired feature, relevant context like error messages or specifications, and labels to categorize the issue.

Reference issues in your commits and pull requests using the # notation:

terminal
git commit -m "Fix temperature sensor parsing, closes #42"

GitHub automatically links the commit to issue #42 and closes the issue when the commit reaches main.

6.5.2 Labels and Milestones

Labels categorize issues: bug, enhancement, documentation, help wanted. Create labels that match your team’s workflow.

Milestones group issues into releases or sprints. Assign issues to a milestone to track progress toward a goal, like “v1.0 Release” or “Sprint 3”.

6.5.3 GitHub Projects

Projects provide Kanban-style boards for visualizing work. Create columns like “To Do,” “In Progress,” and “Done.” Add issues and pull requests to the board and move them between columns as work progresses.

Projects help teams see the big picture: what’s being worked on, what’s blocked, and what’s completed.

6.5.4 Discussions

Discussions provide a forum for conversations that aren’t tied to specific code changes. Use discussions for questions, ideas, announcements, and community engagement.

6.6 Forking: Contributing to Others’ Projects

When you want to contribute to a project you don’t have write access to (common with open-source projects), you use the fork workflow.

A fork is your personal copy of someone else’s repository. You can freely experiment with changes without affecting the original project.

The fork workflow is as follows. First, click “Fork” on the original repository’s GitHub page. This creates a copy under your account. Clone your fork locally:

terminal
git clone https://github.com/your-username/project-name.git

Add the original repository as an “upstream” remote so you can pull in updates:

terminal
git remote add upstream https://github.com/original-owner/project-name.git

Create a branch, make changes, and push to your fork:

terminal
git switch -c fix/typo-in-readme
git commit -am "Fix typo in README"
git push origin fix/typo-in-readme

On GitHub, create a pull request from your fork’s branch to the original repository’s main branch. The maintainers will review your contribution.

To keep your fork synchronized with the original:

terminal
git fetch upstream
git switch main
git merge upstream/main
git push origin main

6.7 GitHub CLI

The GitHub CLI (gh) lets you interact with GitHub from your terminal. This is faster than switching to a browser for common operations.

Check your authentication status:

terminal
gh auth status

Create a new repository:

terminal
gh repo create my-new-project --public --source=. --remote=origin

Create a pull request:

terminal
gh pr create --title "Add anomaly detection" --body "Implements statistical anomaly detection for sensor readings"

List open pull requests:

terminal
gh pr list

Check out a pull request locally for testing:

terminal
gh pr checkout 123

View issues:

terminal
gh issue list
gh issue view 42

The CLI integrates Git and GitHub operations, reducing context switching between terminal and browser.

6.8 Repository Organization

Well-organized repositories are easier to understand and contribute to. Follow these conventions to make your projects professional.

6.8.1 README Files

Every repository should have a README.md file at the root. This is the first thing visitors see. Include the project name and brief description, installation instructions, usage examples, contribution guidelines, and license information.

6.8.2 License

Add a LICENSE file to clarify how others can use your code. For open-source projects, MIT and Apache 2.0 are common choices. For proprietary work, specify that all rights are reserved.

6.8.3 Contributing Guidelines

For collaborative projects, add a CONTRIBUTING.md file explaining how to set up a development environment, coding standards and style guidelines, how to run tests, and the pull request process.

6.8.4 Directory Structure

Organize code logically. A typical Python project structure might be:

output
project-name/
├── README.md
├── LICENSE
├── pyproject.toml
├── src/
│   └── project_name/
│       ├── __init__.py
│       └── main.py
├── tests/
│   └── test_main.py
└── docs/
    └── index.md

6.9 Security Considerations

Never commit secrets to Git. This includes API keys, passwords, database credentials, private keys, and tokens. Once a secret is in Git history, it’s extremely difficult to remove completely.

Use environment variables or dedicated secret management tools for sensitive configuration. Add files containing secrets to .gitignore before you accidentally commit them.

If you do accidentally commit a secret, immediately rotate it (generate a new key) rather than trying to remove it from history. Assume the secret is compromised.

GitHub offers features to help with security. Enable Dependabot to receive alerts about vulnerabilities in your dependencies. Use branch protection rules to require reviews before merging. Consider signing your commits with GPG keys to verify authorship.

6.10 Summary

In this chapter, you learned how GitHub enables collaborative development. You can now synchronize local and remote repositories using push and pull, collaborate using the feature branch workflow and pull requests, participate in code review, use GitHub’s project management features (issues, projects, milestones), contribute to projects you don’t own using forks, and work efficiently with the GitHub CLI.

The combination of Git and GitHub forms the backbone of modern software development. These tools and workflows apply whether you’re working on a two-person team or contributing to projects with thousands of collaborators. Practice these patterns on every project, and they’ll become second nature.

6.11 Glossary

Clone
Creating a local copy of a remote repository, including all files and history.
Fork
A personal copy of someone else’s repository on GitHub. Allows you to experiment freely and propose changes via pull requests.
Merge Conflict
Occurs when Git cannot automatically combine changes because the same lines were modified differently. Requires manual resolution.
Origin
The conventional name for your primary remote repository, typically pointing to GitHub.
Pull
Downloading commits from a remote repository and merging them into your local branch.
Pull Request (PR)
A GitHub feature for proposing that changes from one branch be merged into another. Enables code review and discussion.
Push
Uploading your local commits to a remote repository.
Remote
A Git repository hosted somewhere other than your local machine, such as on GitHub.
Upstream
In the fork workflow, the original repository that you forked from.
Issue
A GitHub feature for tracking tasks, bugs, feature requests, and discussions related to a repository.
Code Review
The practice of examining code changes before they’re merged, checking for bugs, style, and clarity.

6.12 Resources

6.13 Exercises

6.13.1 Question 5.1

What is the relationship between Git and GitHub?

  1. They are the same software
  2. Git is a version control system; GitHub is a hosting platform for Git repositories
  3. GitHub is a version control system; Git is a hosting platform
  4. Git only works when connected to GitHub

6.13.2 Question 5.2

What does git clone do?

  1. Creates a new empty repository
  2. Downloads a complete copy of a remote repository
  3. Uploads local changes to GitHub
  4. Creates a branch of the current repository

6.13.3 Question 5.3

What does git push do?

  1. Downloads changes from a remote repository
  2. Uploads local commits to a remote repository
  3. Creates a new branch
  4. Merges two branches together

6.13.4 Question 5.4

What does git pull do?

  1. Uploads local commits to a remote repository
  2. Downloads commits from a remote repository and merges them
  3. Creates a pull request on GitHub
  4. Deletes a remote branch

6.13.5 Question 5.5

What is a pull request on GitHub?

  1. A request to download a repository
  2. A proposal to merge changes from one branch into another
  3. A request to delete a repository
  4. A request for more storage space

6.13.6 Question 5.6

What is a merge conflict?

  1. When two repositories cannot connect to each other
  2. When Git cannot automatically combine changes because the same lines were modified differently
  3. When a branch is deleted accidentally
  4. When GitHub servers are down

6.13.7 Question 5.7

What is a fork on GitHub?

  1. A tool for splitting large files
  2. A personal copy of someone else’s repository under your account
  3. A type of merge strategy
  4. A way to delete repositories

6.13.8 Question 5.8

What is the conventional name for the primary remote repository?

  1. main
  2. master
  3. origin
  4. upstream

6.13.9 Question 5.9

Why should you NEVER commit secrets (like API keys or passwords) to Git?

  1. Git cannot store special characters
  2. Secrets make the repository too large
  3. Once in Git history, secrets are extremely difficult to remove completely
  4. GitHub automatically rejects commits with secrets

6.13.10 Question 5.10

What is the purpose of code review in the pull request workflow?

  1. To automatically fix bugs in the code
  2. To examine changes for bugs, style, and clarity before merging
  3. To compress the code for faster performance
  4. To convert code between programming languages