Publish, track, update from main
Intermediate Git CLI VS Code UI IntelliJ UI GitLab UI GitHub UI
Why this matters
A branch on your computer is invisible: no colleague can review it, no pipeline can test it, and a broken laptop takes it with them. Publishing costs one command. The second half of this lesson solves the problem that follows: while you work, main moves on, and a branch that ignores that drift turns into a painful merge later.
Publishing a branch
The first push of a new branch needs to say where it goes. Without that, Git stops and tells you exactly what to type:
$ git pushfatal: The current branch docs/12-windows-install-steps has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin docs/12-windows-install-steps
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.-u is the short form of --set-upstream. It pushes and links the two branches in one step:
$ git push -u origin docs/12-windows-install-stepsTo https://gitlab.com/northwind-trails/trailguide.git
* [new branch] docs/12-windows-install-steps -> docs/12-windows-install-steps
branch 'docs/12-windows-install-steps' set up to track 'origin/docs/12-windows-install-steps'.Two things happened: a branch of that name now exists on the remote, and your local branch became a tracking branch. If you set push.autoSetupRemote true in lesson 3.5, a plain git push does all of this for you.
What tracking gives you
The link shows up in three places. In the short status:
$ git status -sb## docs/12-windows-install-steps...origin/docs/12-windows-install-stepsIn the branch list with -vv:
$ git branch -vv* docs/12-windows-install-steps 510f1e0 [origin/docs/12-windows-install-steps] docs: add Windows steps to installation guide (#12)
main 8fa922e [origin/main] Initial import of trailguideAnd in the ahead/behind line of the full git status, which is the one you read every day. Remember from lesson 2.5 that the comparison is against your local bookmark origin/…, which only fetch, pull and push update.
Updating your branch from main
Your branch started at a commit on main. Days later main has moved:
$ git switch main
$ git pullFrom https://gitlab.com/northwind-trails/trailguide
8fa922e..1a01760 main -> origin/main
Updating 8fa922e..1a01760
Fast-forward
data/trails.csv | 1 +
1 file changed, 1 insertion(+)Now your branch is missing that commit. Two ways to fix it, and the difference is the shape of the history.
Merge main into your branch. Safe, always available, works after the branch has been pushed and shared:
$ git switch docs/12-windows-install-steps
$ git merge mainMerge made by the 'ort' strategy.
data/trails.csv | 1 +
1 file changed, 1 insertion(+)$ git log --oneline --graph --all --decorate* 34f6699 (HEAD -> docs/12-windows-install-steps) Merge branch 'main' into docs/12-windows-install-steps
|\
| * 1a01760 (origin/main, origin/HEAD, main) feat: add Coast Walk trail (#29)
* | 510f1e0 (origin/docs/12-windows-install-steps) docs: add Windows steps to installation guide (#12)
|/
* 8fa922e (tag: v1.2.0) Initial import of trailguideThe |\ and |/ marks are the merge: your branch now contains both lines of work, joined by a commit that does nothing but join them.
Rebase your branch onto main. Replays your commits on top of the newer main, so the history stays a straight line:
$ git rebase mainSuccessfully rebased and updated refs/heads/docs/12-windows-install-steps.$ git log --oneline --graph --all --decorate* 5f181fc (HEAD -> docs/12-windows-install-steps) docs: add Windows steps to installation guide (#12)
* 1a01760 (origin/main, origin/HEAD, main) feat: add Coast Walk trail (#29)
| * 510f1e0 (origin/docs/12-windows-install-steps) docs: add Windows steps to installation guide (#12)
|/
* 8fa922e (tag: v1.2.0) Initial import of trailguideLook closely: 5f181fc and 510f1e0 have the same message but different hashes. Rebase re-created your commit on the new base, and the old one is still on the remote. That is rewriting history, and it is why the next push is refused until you force it. Lesson 6.7 covers rebase properly, including that force push.
| Merge main into your branch | Rebase your branch onto main | |
|---|---|---|
| History | Keeps the true shape, adds a merge commit | Straight line, no merge commit |
| Hashes | Your commits keep theirs | Your commits are re-created with new ones |
| After pushing the branch | Safe, just push | Needs --force-with-lease |
| If someone else works on the branch | Safe | Disruptive; do not |
| Conflicts | Resolved once | Possibly once per commit |
Neither is wrong. Teams that squash on merge often prefer rebase for a tidy branch; teams that value the exact history prefer merge. Read your CONTRIBUTING file, and when in doubt, merge: it cannot surprise anyone.
How to do it
$ git push -u origin docs/12-windows-install-steps
$ git switch main && git pull
$ git switch docs/12-windows-install-steps
$ git merge main
$ git pushPublish once, then keep the branch current whenever main moves. git merge main is the safe default.
- Publish: after the first commit on a new branch, the Source Control view shows Publish Branch. Click it. Fallback: Command Palette (Ctrl+Shift+P / ⇧⌘P) → Git: Publish Branch.
- Later pushes use the sync icon in the status bar, which shows arrows with the ahead/behind counts.
- Update from main: Command Palette → Git: Merge Branch… → pick
main. For rebase, Git: Rebase Branch…. - Turn on Git: Autofetch in Settings so the counts stay current without you thinking about it.
- Publish: Git → Push (Ctrl+Shift+K / ⇧⌘K). For a branch that has never been pushed, the dialog shows the new remote branch name and creates it.
- Update from main: open the branches popup (status bar, bottom right), point at
main→ Merge 'main' into current or Rebase current onto 'main'. - Update Project (Ctrl+T / ⌘T) updates the current branch from its own remote branch; its dialog lets you choose merge or rebase as the default.
A pushed branch appears under Code → Branches, with its ahead/behind counts against the default branch and a New button to open a merge request.
Inside an open merge request, GitLab can update the branch for you: the Merge branch button's dropdown offers Rebase when the branch is behind, and some projects show Merge latest changes from main. Both do on the server what the commands above do locally; run git pull afterwards so your copy matches.
A pushed branch appears in the branch dropdown and in the Branches page with ahead/behind counts.
Inside a pull request, the Update branch button appears when main has moved ahead. Its dropdown offers Update with merge commit or Update with rebase. Again, git pull locally afterwards, and after a rebase update your local branch needs git pull --rebase or a reset to match.
Do and don't
Do
- Push a new branch as soon as it has one real commit; it is a backup and it lets colleagues help.
- Update from
mainat least every couple of days, and always before asking for review. - Prefer
git merge mainwhile learning: it never rewrites anything.
Don't
- Don't rebase a branch that a colleague has also checked out.
- Don't let a branch run for weeks without updating; the conflicts compound.
- Don't force-push to "fix" a rejected push before reading lesson 6.7; the rejection may mean a colleague pushed.
Common mistakes
fatal: The current branch … has no upstream branch. The first push needs-u origin <branch>; Git prints the exact line to copy.git statusshows no ahead/behind line. The branch has no upstream yet. Push with-u.- Pushing a rebased branch and seeing
rejected. Expected: the remote still has the old commits.--force-with-lease, and only on a branch that is yours (lesson 6.7). - Merging
maininto a branch and calling it "merging the branch". This direction bringsmain's work into your branch. The other direction, which puts your work intomain, is lesson 6.6 and normally happens through a merge request.
Try it yourself
Goal: publish a branch, watch it fall behind, and bring it up to date.
- From an up-to-date
main, createdocs/practice-publish, add a line todocs/faq.md, commit. - Publish it:
git push -u origin docs/practice-publish. Read the two output lines. - Make
mainmove:git switch main, add a line toREADME.md, commit, push. - Go back to the branch and check the shape:
git log --oneline --graph --all --decorate -4. - Bring
mainin:git merge main. Look at the graph again.
Expected result: step 2 prints * [new branch] and set up to track; after step 3 the graph forks; after step 5 a merge commit joins the two lines and your branch contains the README change.
Show solution
$ git switch -c docs/practice-publish
$ printf '\n## Practice\n\nA line.\n' >> docs/faq.md
$ git commit -am "docs: practice publish"
$ git push -u origin docs/practice-publish
$ git switch main
$ printf '\nA line on main.\n' >> README.md
$ git commit -am "docs: move main forward"
$ git push
$ git switch docs/practice-publish
$ git merge maingit switch main, git branch -D docs/practice-publish, git push origin --delete docs/practice-publish (lesson 6.8).