2026 maintenance note: The original 2019 export is preserved verbatim near the end of this page. It reflects a direct-to-
masterworkflow and contains an original typo; treat it as an archive, not as current instructions. The maintained guide below assumes a Git hosting service with pull requests or merge requests. Replacemainwith your repository’s actual default branch and follow its documented team policy.
Table of Contents
The small-team contract
Before choosing commands, agree on four rules:
- Protect the default and release branches; do not push directly to them during normal work.
- Make each change on a short-lived branch and integrate it through review.
- Run the repository’s tests and inspect the exact diff before requesting review.
- Do not rewrite a branch that another person may have based work on.
Git itself does not enforce review. A hosting platform can: for example, GitHub branch protection can require pull-request reviews, passing status checks, and resolved conversations, and can block force pushes. These are repository settings, not universal Git behavior.
1. Inspect first, then start from the remote default branch
Check where you are and whether you have unfinished work:
git status --short --branch
git branch --show-current
git remote -v
Find the remote’s advertised default branch with git remote show origin, or check the repository page. The rest of this guide uses main as an example.
Fetch remote updates without changing your working branch or files:
git fetch origin --prune
git log --oneline --decorate --graph -20 --all
Then create a focused branch from the current remote default branch:
git switch --create feature/login-timeout origin/main
git fetch updates remote-tracking references. By contrast, git pull first fetches and then integrates into the current branch, so a bare git pull can merge or rebase according to configuration. Fetching and inspecting first makes that boundary visible.
2. Build a reviewable change
Keep the branch about one problem. Before committing, separate the working-tree diff from the staged diff:
git status --short
git diff
git add --patch
git diff --cached
git commit -m "Handle login timeout explicitly"
git add --patch is useful when a file contains both relevant and unrelated edits. Run the project’s formatter, tests, and security checks; those commands differ by repository and cannot be inferred from Git.
Review what the pull request will contain relative to the base branch:
git fetch origin
git diff --stat origin/main...HEAD
git diff origin/main...HEAD
git log --oneline origin/main..HEAD
The three-dot diff compares the branch tips from their merge base, which usually matches the change a pull-request interface presents.
3. Publish the branch and request review
Push the topic branch, not the default branch:
git push --set-upstream origin feature/login-timeout
Open a pull request or merge request with:
- the problem and scope;
- the testing performed and its result;
- operational or migration risks;
- screenshots or logs when they make behavior easier to verify;
- a linked issue, when one exists.
Reviewers should examine the current diff, not merely the description. Address requested changes, rerun relevant checks, and leave the final merge to the repository’s configured method and permissions.
4. Choose one integration policy
Merge, rebase, and squash answer different questions. A team should choose at repository level instead of switching methods ad hoc.
| Method | What it does | Appropriate boundary | Main caution |
|---|---|---|---|
| Merge | Joins two histories and may create a merge commit | Shared branches, or a repository that deliberately records branch topology | Can add noisy merge commits if used mechanically |
| Rebase | Replays commits onto a new base and creates new commit IDs | Your own topic branch, before others depend on it, when team policy permits | Rewriting a shared branch can invalidate other people’s work |
| Squash merge | Integrates a pull request as one default-branch commit | Small changes where intermediate commits have little lasting value | Loses the topic branch’s individual commit boundaries on the target |
To bring the latest main into a topic branch without rewriting the topic branch, merge:
git fetch origin
git switch feature/login-timeout
git merge origin/main
To replay your own unshared topic branch on the latest main, rebase only when the team permits it:
git fetch origin
git switch feature/login-timeout
git rebase origin/main
git push --force-with-lease origin feature/login-timeout
--force-with-lease checks an expected remote state and is safer than a blind --force, but it is still a history rewrite. Coordinate before using it, never use it on the protected default branch, and avoid it when someone else may be using the topic branch.
5. Resolve conflicts deliberately
When a merge or rebase stops, do not delete conflict markers blindly. First identify every unresolved path:
git status
git diff --name-only --diff-filter=U
Edit each file into the intended final result, remove the <<<<<<<, =======, and >>>>>>> markers, run relevant tests, then stage the resolution.
For a merge:
git add path/to/resolved-file
git merge --continue
For a rebase:
git add path/to/resolved-file
git rebase --continue
If the chosen integration was wrong or the resolution is uncertain, return to the pre-operation state:
git merge --abort
During a rebase:
git rebase --abort
The two abort commands apply only while their corresponding operation is in progress.
6. Recover without rewriting shared history
Use the least destructive tool that matches the state:
| Situation | Inspect first | Safer recovery |
|---|---|---|
| A path was staged by mistake | git diff --cached -- path/to/file |
git restore --staged path/to/file |
| Unstaged working-tree edits in a path should be discarded | git diff -- path/to/file |
git restore --worktree path/to/file |
| A bad commit is already shared | git show <commit> |
git revert <commit> and review the new inverse commit |
| A local commit seems lost | git reflog |
git branch rescue-work <commit> |
Work was committed on a detached HEAD |
git status and git log -1 |
git switch --create rescue-work before switching away |
git restore --worktree discards uncommitted working-tree content for the named path; copy anything needed elsewhere first. git revert records a new commit and therefore preserves shared history. Reflogs are local, time-limited records rather than permanent backups, so create a rescue branch as soon as the desired commit is found.
Avoid treating git reset --hard, plain git push --force, or branch deletion as routine troubleshooting. They can discard reachable work or rewrite collaborators’ history.
7. Diagnose common collaboration failures
Push rejected as non-fast-forward
Someone or something advanced that remote branch. Do not force-push over it. Fetch and inspect:
git fetch origin
git status --short --branch
git log --oneline --left-right --graph HEAD...origin/feature/login-timeout
Then merge or rebase according to the branch’s ownership and team policy. If the unexpected commits are not yours, coordinate with their author.
“Your branch and origin have diverged”
This means both sides contain commits absent from the other; it does not tell you whether merge or rebase is correct. Inspect the graph, identify the commits and authors, then use the agreed integration policy.
Detached HEAD
Inspection in detached state is valid, but new commits have no branch name. If the work matters, attach it before leaving:
git switch --create rescue-detached-work
Pull request changed after approval
Review the new diff and rerun required checks. Hosting rules can dismiss stale approvals or require approval of the latest push; do not assume an earlier approval covers later commits.
A compact repeatable workflow
git status --short --branch
git fetch origin --prune
git switch --create feature/login-timeout origin/main
git diff
git add --patch
git diff --cached
git commit -m "Handle login timeout explicitly"
git diff origin/main...HEAD
git push --set-upstream origin feature/login-timeout
Edit and run the repository-specific checks after creating the branch. Open the pull request after pushing; review, required checks, and the repository merge policy follow. This is a baseline, not a substitute for the repository’s CONTRIBUTING file, release process, access controls, or incident procedure.
—
2019 original export (verbatim archive)
Archive boundary: The text below is the complete body from
out/posts/2019-04-20-git-version-control-team-development-1865/index.md, exported from post 1865 and dated 20 April 2019. Its wording, typo, commands, branch name, and historical claims are preserved without correction. Do not follow it as the maintained workflow.
Pull before edit and push you code
git pull
View your current branch
git branch
Create and switch to created branch
git branch branchname
git checkout branchname
Merge, delete and push your code to server
git checkout master + git merge branchname
git branch -d branchname
git push origin branchname
—
