Chapter 8 · practice
Collaborating Locally
Bring a Branch Up to Date
Two people can start from the same
Meet the three repositories
This chapter stays entirely inside one practice workspace:
/workspace/
├── shop/ your working repository
├── origin.git/ the bare repository used to exchange history
└── colleague/ an observation clone that must remain unchanged
The prepared shop main, and its working tree is clean. Its local main has two receipt commits. Its remote-tracking ref origin/main records two quantity commits that came through colleague. Both lines begin at the same earlier commit.
Start with commands you already know:
pwd
git status
The status report says that main and origin/main have diverged and gives an ahead/behind count. “Ahead by 2” means local main reaches two commits that origin/main does not. “Behind by 2” means origin/main reaches two commits that local main does not. These counts describe reachability between commit histories, not a score and not a count of changed files.
Refresh what this repository knows
The command git fetch contacts the saved origin repository, downloads commits and refs that are missing here, and updates remote-tracking refs such as origin/main. It does not move local main and does not change the working tree. Run it before making a collaboration decision so that you reason from the latest information this repository can get:
git fetch
git status
In this deterministic workspace, origin/main was already current, so the ahead/behind count stays at two and two. That unchanged result is still useful evidence: you checked rather than guessed.
Compare each side of the split
A history range lets git log show commits reachable from one name but not another. In A..B, the name on the right is the side Git shows, while commits also reachable from the name on the left are excluded. The --oneline option presents each matching commit as an abbreviated ID and its subject, which makes the two short lists easier to compare. The first command below therefore shows the colleague-side commits missing from local main; the second reverses the range and shows the local commits missing from origin/main:
git log --oneline main..origin/main
git log --oneline origin/main..main
Read the subjects before integrating. The colleague side adds quantity handling and documents it. Your side adds receipt behavior and a test. The changes are different but compatible, so both belong in the result.
Why the first push must stop
git push asks the bare origin to move its main branch to your local main. Right now that move would discard the two colleague commits that only origin reaches. Git rejects this non-fast-forward push because the requested new tip does not contain the current remote tip. Run the ordinary command and read the rejection:
git push
The rejection is protection, not a demand to force the push. Recovery has three steps: refresh remote knowledge, integrate the remote-tracking ref into the local branch, and then push the integrated result. You already fetched and inspected both sides, so integration is next.
Integrate without losing either side
You met git merge in Chapter 6. Here, git merge origin/main means “bring the commit history named by my remote-tracking ref into the branch I am on.” Because both sides have unique commits, Git creates a merge commit with two parents. The -m option supplies its message directly so no editor needs to open. The seed was designed so this merge completes without a conflict:
git merge origin/main -m "Merge origin main"
git status
After the merge, git status reports a clean tree and says local main is ahead of origin/main. That is expected: the integrated commit exists only in shop until the next lesson pushes it.
One honest word about rebase
You will hear that git rebase is the other way to do what you just did, and that is true. A merge keeps both lines exactly as they happened and adds a commit recording where they joined. A rebase copies your commits onto the end of the other line instead, giving a straighter story and new identities to your commits.
Neither one is the right answer. Teams pick a habit, mostly according to whether rewriting their own commits is safe and what they have agreed between themselves. This course practices merge, because it never rewrites a commit a colleague may already hold, and because the join stays visible afterwards. If you join a team that rebases, everything before the integration step, fetching and reading both sides, is identical.
Your first git push was rejected. What was Git protecting?
git status said main was ahead by 2 and behind by 2. What does that describe?
Both lines of work now sit in one history, and the merge commit records the point where they met. Nobody’s work was chosen over anybody else’s, which is the outcome worth wanting when the other line belongs to a person rather than to you.
Your repository is now ahead of the shared one. Closing that gap is the next lesson, and this time the push will be accepted.