Collaborative Workflows: Forks, Upstreams, Pull Requests, and Reviewable History: Guided Hands-On Workflow and Core Operations
Simulate fork-based collaboration entirely locally: authoritative and fork bare repositories, upstream synchronization, clean topic history, publication, patch-based review, and merge/squash/linear graph outcomes.
Learning objectives
- Create an authoritative repository and contributor fork using local bare repositories.
- Add and inspect a conventional upstream remote without confusing it with branch tracking.
- Synchronize an unpublished topic branch safely against a current authoritative target.
- Publish a reviewable topic to the fork and export its commits as patches without a hosted account.
- Compare merge-commit, squash, and rebased-linear integration outcomes at the Git graph level.
1. Build a local fork-equivalent topology
This lab uses filesystem repositories, so no hosted account, token, SSH key, or internet connection is required. The directory layout represents an authoritative repository, a contributor fork, and local working clones.
Git Bash, Bash, or zsh
mkdir git-collab-lab
cd git-collab-lab
git init --bare upstream.git
git clone upstream.git seed
cd seed
git switch -c trunk
git config user.name "Project Maintainer"
git config user.email "maintainer@example.invalid"
printf "# Service\n" > README.md
printf "port=8080\n" > service.conf
git add README.md service.conf
git commit -m "Initialize service project"
git push -u origin trunk
cd ..
git --git-dir=upstream.git symbolic-ref HEAD refs/heads/trunk
git clone --bare upstream.git fork.git
git clone fork.git contributor
git clone upstream.git integrator
What changed: upstream.git and
fork.git are bare repositories containing Git
database/refs but no checked-out working tree. The two normal clones
provide working trees. The fork is simply another repository that
initially contains the same history.
2. Give the contributor clone conventional remote names
cd contributor
git remote -v
git remote add upstream ../upstream.git
git remote -v
git fetch upstream
git branch -vv
git for-each-ref --format='%(refname:short) %(objectname:short)' refs/remotes
origin points to fork.git. The newly added
upstream points to the authoritative repository. Fetch
creates/updates upstream/trunk according to the
remote's fetch refspec; it does not change local trunk.
3. Create a focused topic from the authoritative base
git switch -c topic-health upstream/trunk
git config user.name "Contributor"
git config user.email "contributor@example.invalid"
printf "health_endpoint=/healthz\n" >> service.conf
git add service.conf
git diff --staged
git commit -m "Expose health endpoint for probes"
printf "\n## Health check\nUse /healthz for readiness probes.\n" >> README.md
git add README.md
git diff --staged
git commit -m "Document readiness probe endpoint"
git status --short --branch
git log --graph --decorate --oneline --all --max-count=12
The two commits form a small reviewable series: one behavior/configuration change, then documentation describing operational use. They are unpublished so far.
4. Advance the authoritative branch independently
Use the integrator clone to simulate another accepted change.
cd ../integrator
git config user.name "Integrator"
git config user.email "integrator@example.invalid"
printf "owner=platform-team\n" >> service.conf
git add service.conf
git commit -m "Record service ownership"
git push origin trunk
git log --oneline -3
cd ../contributor
git fetch upstream
git log --graph --decorate --oneline --all --max-count=15
git rev-list --left-right --count upstream/trunk...topic-health
The graph now shows divergence: the authoritative branch has work the topic did not start with, and the topic has two proposal commits.
5. Choose a synchronization method from history policy
For an unpublished topic owned by one contributor, rebasing onto the current target can produce a straightforward review series. For a topic already consumed by others, merging the target branch into the topic preserves existing commit identities and is often safer.
git status --short
git rebase upstream/trunk
git log --graph --decorate --oneline --all --max-count=15
git merge-base upstream/trunk topic-health
git log --oneline upstream/trunk..topic-health
git diff --stat upstream/trunk...topic-health
The content is still the proposal, but the two topic commits now have new parentage and therefore new object IDs. Chapter 09 explains rebase reconstruction in depth.
6. Publish the topic to the contributor fork
git push --dry-run -u origin topic-health
git push -u origin topic-health
git branch -vv
git ls-remote --heads origin topic-health
The topic branch now exists in fork.git. A hosting
platform could use that ref as a review source, but the local lab
needs no review UI to inspect or integrate it.
7. A review can also be represented as refs plus patches
Git can serialize each non-merge commit as a mail-style patch message. This is not a hosted pull request, but it demonstrates that a reviewable change series can travel without a platform account.
mkdir -p review-patches
git format-patch --output-directory review-patches upstream/trunk..topic-health
ls review-patches
git log --reverse --format='%h %s' upstream/trunk..topic-health
Chapter 23 covers patch/email maintainer workflows thoroughly; here the command simply reinforces that commit series and hosted review records are separate concepts.
8. Compare integration graph outcomes in isolated local refs
Create an isolated comparison clone so the authoritative remote is not changed.
cd ..
git clone upstream.git compare
cd compare
git config user.name "Graph Reviewer"
git config user.email "reviewer@example.invalid"
git remote add contributor ../fork.git
git fetch contributor topic-health
git branch integrate-merge trunk
git branch integrate-squash trunk
git branch integrate-linear trunk
Outcome A — merge commit
git switch integrate-merge
git merge --no-ff contributor/topic-health -m "Merge reviewed health topic"
git log --graph --decorate --oneline --max-count=8
The target history records both topic commits plus a two-parent merge commit.
Outcome B — squash
git switch integrate-squash
git merge --squash contributor/topic-health
git status --short
git diff --staged --stat
git commit -m "Add reviewed health endpoint"
git log --graph --decorate --oneline --max-count=8
--squash prepared the combined content but did not
create a merge commit or parent relationship to the topic; the
explicit commit creates one new single-parent commit.
Outcome C — rebased/linearized topic then fast-forward integration
git switch -c topic-linear contributor/topic-health
git rebase trunk
git switch integrate-linear
git merge --ff-only topic-linear
git log --graph --decorate --oneline --max-count=8
This produces a linear target history. The topic commits may have
been recreated if their old base differed from trunk.
9. Once others consume commits, preserve that fact in your decision
If a reviewer has fetched, commented on, tested, or built artifacts from specific commit IDs, rewriting those commits makes the old identifiers stale. A small correction can still be added as a new commit. If policy permits rewriting an unpublished/private series, communicate it and use guarded force updates when publishing the replacement. Chapter 09 provides the full safety model.
10. Challenge — choose collaboration operations from the graph
- Your topic is unpublished and the target branch advanced by one commit. Which local integration choice can keep the topic linear?
- Your teammate already based work on your published topic commits. Which synchronization choice preserves their existing commit IDs?
- You need to show a reviewer only topic commits not in the authoritative target. Which log range answers that?
- You have no hosting account. Which Git mechanism can package the series for review/transport?
11. Cleanup
Git Bash / Bash / zsh
cd ../..
pwd
rm -rf git-collab-lab
PowerShell
Set-Location ../..
Get-Location
Remove-Item -Recurse -Force git-collab-lab
12. Knowledge check
Question 1. After git fetch upstream, why might
your local trunk still be behind?
upstream/trunk. It does not automatically move your
local branch.
Question 2. Why was rebase acceptable for
topic-health before its first push?
Question 3. What topology difference does squash integration create?
Question 4. Does git format-patch create a pull
request?
13. Summary
You simulated an authoritative project and contributor fork with
bare repositories, added an upstream remote,
synchronized an unpublished topic, published it to the fork,
exported a patch series, and compared merge, squash, and linearized
outcomes without changing shared authoritative history.
Authoritative references
git-clone
git-remote
git-fetch
git-rebase
git-merge
git-format-patch
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.