Branching, Merging, and History ManagementIntroductionVersion control becomes especially powerful when a project has several lines of development. A team may need to develop a feature, correct a production defect, test an experiment, or maintain an older release without interrupting the main line of work. Git supports these activities through branches and a directed history of commits. Branching is not merely a command-line technique. It is a method of managing parallel work, coordinating people, protecting deployable code, and recording the evolution of a software system. Merging and rebasing determine how independent lines of work are brought together. Cherry-picking, resetting, reverting, and reflog recovery provide different mechanisms for correcting or reorganising history. Each has distinct safety conditions. This chapter explains these operations and develops practical criteria for selecting among them. The central professional principle is simple: local history may be rewritten when its consequences are controlled; shared history should normally be preserved. Learning ObjectivesBy the end of this chapter, you should be able to: - create, inspect, switch, rename, and delete branches;
- explain commits, references, ancestry, and the commit graph;
- merge branches and interpret fast-forward and three-way merges;
- use rebasing appropriately and identify its risks;
- apply cherry-pick, reset, revert, and reflog operations;
- diagnose and resolve merge conflicts safely;
- select history-management techniques according to collaboration and release conditions;
- apply branch protection, review, and recovery practices in GitHub or GitLab.
1. The Git Commit GraphA Git commit is a snapshot of tracked files accompanied by metadata, including its author, message, parent commit(s), and identifier. A normal commit has one parent. A merge commit normally has two or more parents. Git stores relationships between commits rather than a simple editable list of file versions. A branch is a movable reference, or name, pointing to a commit. For example, a branch named main may point to commit C. When a new commit is made while main is checked out, the branch reference advances to the new commit. The earlier commit remains in the graph as an ancestor. HEAD identifies the currently checked-out commit, usually through the current branch. In the following simplified history, arrows indicate parent relationships:
A ← B ← C (main)
\
D ← E (feature)Here, feature and main share commits A, B, and C, while E contains work not present on main. A branch does not duplicate the entire repository. It is a lightweight reference, which is why creating branches is normally inexpensive. Useful inspection commands include: git status
git branch
git branch --all
git log --oneline --graph --decorate --all
git show <commit>
git diff main..feature
git diff main...feature The two-dot and three-dot forms have different meanings. main..feature identifies commits reachable from feature but not from main. main...feature is commonly used by git diff to compare each branch with their common ancestor, helping show the changes introduced by the feature branch. 2. Creating and Managing BranchesA branch should generally represent a coherent purpose: a feature, defect correction, release line, or short-lived experiment. Branches that remain open for a long time accumulate divergence and increase integration difficulty. Typical commands are: git switch -c feature/login-validation
git switch main
git branch --move old-name new-name
git branch --delete feature/login-validation
git branch --merged main
git branch --no-merged main git switch is designed for branch switching. The older git checkout command can also switch branches, but it combines branch and file-restoration functions and can be less explicit. A remote-tracking branch records the last known state of a branch on a remote, such as origin/main; it is not automatically updated until a fetch occurs.
git fetch origin
git switch --track -c feature/login-validation origin/feature/login-validation
git push --set-upstream origin feature/login-validation Before creating a branch, inspect the working tree and decide whether uncommitted changes should be committed, stashed, or discarded. A clean working tree makes later reasoning considerably safer. Branching modelsA small team may use a simple model with main and short-lived feature branches. A release-oriented organisation may maintain release branches while using hotfix branches for urgent production corrections. GitFlow-style models introduce long-lived develop, release, and hotfix branches, but they can create considerable integration overhead. Trunk-based development instead keeps branches very short-lived and integrates frequently into a protected main line. No model is universally superior. The choice should reflect deployment frequency, testing automation, regulatory controls, team size, and the cost of maintaining multiple supported releases. 3. Merging: Combining Lines of DevelopmentMerging combines the histories of two lines of development. First, update the receiving branch and check it out: git switch main
git pull --ff-only origin main
git merge --no-ff feature/login-validation The receiving branch is sometimes called the current branch; the other branch is the merged branch. Fast-forward mergeIf the current branch is an ancestor of the selected branch, Git can move the current branch reference forward without creating a new commit: A ← B (main)
← C ← D (feature)After a fast-forward, main points to D. The history is linear. To require this behaviour and prevent an accidental merge commit, use: git merge --ff-only feature/login-validation Three-way mergeIf both branches have new commits, neither is an ancestor of the other. Git identifies their best common ancestor and compares each branch with it. If the changes do not overlap incompatibly, Git creates a merge result. With --no-ff, a merge commit is created even when fast-forwarding would technically be possible, preserving the fact that a topic branch existed. C ← D (feature)
/
A ← B
\
E (main)A merge commit records both parent lines. This is valuable when the topology of integration is important, although excessive merge commits can make history difficult to read. Common policies include: --ff-only: preserve linear history and reject non-linear integration;--no-ff: preserve explicit branch boundaries;- platform pull-request merge: integrate only after review and automated checks.
4. Rebasing and History TransformationRebasing copies a sequence of commits and places the copies on a new base. Suppose a feature branched from B while main advanced to E: C ← D (feature)
/
A ← B ← E (main)After git switch feature followed by git rebase main, Git creates new commits C′ and D′ based on E: A ← B ← E ← C′ ← D′ (feature) The copied commits have new identities because commit identity depends on content, metadata, and parent information. Rebasing therefore rewrites history; it does not move existing commits. git switch feature/login-validation
git fetch origin
git rebase origin/main During a conflict: git status
# edit conflicted files
git add <resolved-file>
git rebase --continue To abandon the operation: git rebase --abort Rebasing is useful for a private feature branch that needs a current base or a clean sequence of commits before review. It is dangerous when commits have already been shared and others have based work on them. After rebasing a branch that was previously pushed, updating the remote may require: git push --force-with-lease --force-with-lease is safer than --force because it refuses to overwrite the remote if it has advanced unexpectedly. It is still not a substitute for communication and branch protection.
Interactive rebaseInteractive rebase permits local commit improvement: git rebase -i HEAD~4 The editor can mark commits as pick, reword, edit, squash, or fixup. This is appropriate for combining noisy work-in-progress commits, correcting messages, or arranging a logical series before publication. It should not be used casually on a shared branch. 5. Cherry-Picking Selected CommitsCherry-pick applies the change introduced by an existing commit onto the current branch, producing a new commit. git switch release/2.4
git cherry-pick <commit-id> It is useful when a single defect correction must be transferred to a maintenance branch without bringing an entire feature branch. It can also be useful for emergency fixes, although a coordinated branch strategy is preferable for repeated transfers. Cherry-picking duplicates the logical change but not the original commit identity. Repeated cherry-picks may complicate later merges, especially if the same change is modified independently. Record the reason in the commit message or issue tracker. To stop or abandon a conflicted cherry-pick: git cherry-pick --continue
git cherry-pick --abort 6. Reset, Revert, and ReflogThese commands solve different problems and must not be treated as interchangeable. Resetgit reset moves the current branch reference and optionally changes the staging area and working tree.
| Mode | Branch reference | Index | Working tree | Typical use |
|---|
--soft | moved | unchanged | unchanged | redo or combine recent commits | --mixed (default) | moved | reset | unchanged | unstage or revise commits locally | --hard | moved | reset | reset | discard tracked local changes |
For example: git reset --soft HEAD~1
git reset HEAD~1
git reset --hard HEAD~1 --hard can destroy uncommitted work. It should be used only when the user has verified that the changes are unnecessary or backed up. Resetting a private branch that has not been shared is generally safe. Resetting a public branch changes what collaborators see and may require force-pushing, so it is usually inappropriate.
Revertgit revert creates a new commit that reverses the effect of an earlier commit:
git revert <commit-id> Because it preserves the existing history, revert is normally the correct response when a faulty commit has already entered a shared or protected branch. Reverting a merge commit requires choosing a mainline parent, for example: git revert -m 1 <merge-commit> The selected parent expresses which side should be regarded as the main line. This decision must be made carefully because reverting a merge can affect later attempts to reintroduce related work. ReflogThe reflog records movements of local references such as HEAD, including resets, rebases, and branch switches. It is a recovery aid, not a permanent remote backup. git reflog
git show HEAD@{2}
git branch recovery HEAD@{2}If a reset or rebase appears to lose commits, inspect the reflog, identify the desired commit, and create a recovery branch before further changes. Reflog entries are local and eventually expire according to repository maintenance settings. They do not normally recover objects that were never present locally or that have been removed from every repository. 7. Conflict Detection and ResolutionA conflict occurs when Git cannot automatically reconcile changes. Conflicts commonly arise when two branches modify overlapping lines, rename files inconsistently, or alter related structural elements. During a conflict, Git marks files with delimiters such as: <<<<<<< HEAD
content from the current branch
=======
content from the other branch
>>>>>>> feature/login-validation The correct procedure is: - read the conflict context rather than selecting a side mechanically;
- edit the file into the intended final form;
- remove all conflict markers;
- run formatters, linters, unit tests, and relevant integration tests;
- stage the resolved file with
git add; - continue the operation with
git merge --continue, git rebase --continue, or git cherry-pick --continue as appropriate; - abort if the intended result cannot be established safely.
For a merge, git merge --abort attempts to restore the pre-merge state. Conflict resolution is a semantic task: Git can identify competing text but cannot determine business intent. A developer should consult the issue, tests, code owners, and domain specialists when necessary. Useful tools include: git diff
git diff --check
git status
git mergetool Do not mark a file resolved merely because the conflict markers have disappeared. A syntactically valid resolution may still be logically incorrect. 8. Selecting a Safe TechniqueThe following decision framework supports professional judgement. | Situation | Usually appropriate technique |
|---|
| Integrate a completed branch while preserving topology | merge or pull request | | Update a private branch before review | rebase | | Transfer one fix to a maintenance branch | cherry-pick, followed by testing | | Undo a public faulty commit | revert | | Rework unpublished local commits | reset or interactive rebase | | Recover after an accidental local reset | reflog | | Discard confirmed unwanted local changes | carefully verified hard reset |
Before rewriting history, ask: - Has the commit been pushed?
- Could another person have based work on it?
- Is the branch protected?
- Is there a backup or recovery point?
- Can the operation be explained to the team?
- Have automated and manual tests been run afterward?
9. Applied Case: Emergency Correction in a Release BranchBackgroundThe fictional company Northstar Logistics deploys from main and maintains release/4.2 for security and stability fixes. Feature development occurs on short-lived branches and is reviewed through GitLab merge requests. ProblemA defect in address validation reaches main and is discovered after release 4.2 has already branched. The correction exists in commit 8f31a2c on main, but the release branch does not contain the feature work that surrounds it. AnalysisMerging all of main into release/4.2 would introduce unrelated features and increase release risk. Resetting the release branch would rewrite shared history. Reverting the original defect commit on main would not transfer the correction to the release line. The required operation is a carefully reviewed cherry-pick. ApproachThe release engineer first updates remote references and creates a safety tag: git fetch origin
git switch release/4.2
git pull --ff-only origin release/4.2
git tag safety/release-4.2-before-address-fix
git cherry-pick 8f31a2c A conflict occurs because the release branch uses an older validation module. The engineer examines both implementations, consults the issue specification, adapts the correction to the older interface, stages the result, and continues: git add src/address_validator.py
git cherry-pick --continue The pipeline runs unit, integration, security, and regression tests. A merge request is opened for the release branch, and deployment occurs only after approval. OutcomeThe targeted correction enters release 4.2 without importing unrelated development. The release branch retains an auditable commit and review record. The team later documents that the fix must also remain represented in the main development line, preventing divergence. Learning points- A branch is a delivery boundary as well as a technical reference.
- Cherry-pick is useful for selective maintenance work, but it creates a new commit and requires testing.
- Tags and protected branches provide recovery and governance controls.
- Conflict resolution requires understanding the target branch, not merely copying source text.
10. GitHub and GitLab GovernancePlatforms add collaboration controls around Git operations. Protected branches can require pull or merge requests, successful CI checks, signed commits, code-owner approval, and multiple reviewers. These controls reduce accidental force-pushes and make shared history more reliable. A practical policy may require: - no direct pushes to
main; - successful build, test, security, and quality checks before merging;
- linear history where the organisation values simple rollback and auditability;
- merge commits where preserving integration context is important;
- restricted force-push permission;
- documented emergency procedures;
- tags for release candidates and production releases;
- regular deletion of merged short-lived branches.
Commit messages should explain intent, while issue and merge-request descriptions explain context and risk. Signed commits can improve authorship assurance, but signatures do not prove that the change is correct. Access control, review, CI, and least-privilege permissions remain necessary. History management also has ethical and governance implications. Rewriting history can conceal accountability, invalidate audit references, or remove evidence needed for incident investigation. In regulated environments, retention, approvals, traceability, and immutable release artifacts may be required. Teams should therefore distinguish cosmetic cleanup from alteration of an official record. 11. Contemporary Practices and LimitationsModern development increasingly combines short-lived branches, automated validation, and continuous delivery. Pull requests provide a review boundary, while merge queues can serialise validated changes so that the tested result matches the eventual target branch. git rerere can record and reuse conflict resolutions, but it should be enabled only when the team understands its effect and verifies reused resolutions. Git is distributed, so local history and remote history can temporarily differ. This improves resilience but creates coordination challenges. Reflog is powerful locally but is not a central audit system. Large binary assets, generated files, and monolithic repositories may require Git LFS, repository partitioning, or specialised build and artifact systems. AI-assisted coding tools may generate commits or propose conflict resolutions. Such output must be reviewed like any other code. An AI system cannot reliably infer undocumented business intent, security obligations, licensing restrictions, or the correct parent during a complex merge. Human review, automated tests, and traceable approvals remain essential. Best-Practice Checklist- Keep branches focused and short-lived where possible.
- Synchronise with the remote before integrating.
- Use
--ff-only when accidental merge commits are unacceptable. - Rebase private work, not shared work, unless the team explicitly agrees.
- Prefer
revert for undoing changes on public branches. - Use
reset --hard only after confirming that data may be discarded. - Use
--force-with-lease, never casual force-pushing, when a rewrite is authorised. - Resolve conflicts semantically and test the final result.
- Tag releases and create recovery points before risky operations.
- Protect important branches with review and CI policies.
- Use reflog promptly when recovery is needed.
Chapter SummaryBranches are movable references in Git’s commit graph and enable parallel development without duplicating the repository. Merging combines histories and may be fast-forward or three-way. Rebasing copies commits onto a new base and produces rewritten identities, making it suitable mainly for controlled private work. Cherry-pick transfers a selected change as a new commit. Reset moves local references and may alter the index and working tree, whereas revert preserves shared history by creating an inverse commit. Reflog records local reference movements and is an important recovery mechanism. Conflicts require semantic judgement, testing, and careful continuation or abortion of the operation. Safe history management depends on whether work is private or shared, whether auditability matters, and whether collaborators may rely on existing commit identities. GitHub and GitLab strengthen these practices through protected branches, reviews, CI, permissions, and release controls. Key TermsBranch: A movable reference to a commit. Commit: A recorded snapshot with metadata and parent relationship(s). HEAD: The symbolic reference identifying the current checkout. Ancestor: A commit reachable by following parent links backward. Fast-forward: Moving a branch reference forward without creating a merge commit. Three-way merge: A merge using two branch tips and their common ancestor. Merge commit: A commit with multiple parents that records integration. Rebase: Replaying commits onto a different base commit. History rewriting: Changing commit ancestry or identities. Cherry-pick: Applying one existing commit’s change as a new commit. Reset: Moving a branch reference and optionally changing index and working tree. Revert: Creating a new commit that reverses an earlier change. Reflog: A local log of reference movements. Conflict: A situation requiring human resolution because automatic integration failed. Remote-tracking branch: A local reference representing a remote branch’s last fetched state. Force-with-lease: A conditional force push that checks the expected remote state. Protected branch: A branch governed by restrictions such as review or CI requirements. Merge request/pull request: A platform-based proposal for reviewing and integrating changes. Review QuestionsShort Answer Questions- What is the relationship between a branch and a commit?
- Distinguish a fast-forward merge from a three-way merge.
- Why does rebasing change commit identities?
- What is the principal difference between reset and revert?
- What information does the reflog provide?
Long Answer Questions- Explain the complete process of creating, updating, reviewing, and integrating a feature branch.
- Compare merge and rebase, including their effects on history, collaboration, and auditability.
- Describe the reset modes and give an appropriate use case for each.
- Explain a disciplined procedure for resolving a merge conflict.
- Discuss how GitHub or GitLab protections improve the safety of shared history.
Analytical / Application Questions- A developer has rebased a private feature branch, but the remote branch has received another developer’s commit. What should the developer inspect and why is
--force-with-lease preferable to --force? - A security fix is present in
main but must be transferred to an older release branch without importing unrelated features. Which technique should be selected, and what testing and governance steps should follow? - A faulty commit has already been merged into a protected production branch. Compare reset, revert, and reflog recovery, and recommend the safest immediate response.
Multiple Choice Questions with AnswersQuestion 1What does a Git branch primarily represent? A. A complete duplicate repository B. A movable reference to a commit C. A permanent copy of the working tree D. A remote server connection Correct Answer: B. A movable reference to a commit Question 2Which command prevents a merge unless the current branch can be advanced without a merge commit? A. git merge --no-ff B. git merge --squash C. git merge --ff-only D. git merge --abort Correct Answer: C. git merge --ff-only Question 3Why is rebasing a shared branch risky? A. It deletes all remote branches B. It changes the identities and ancestry of commits C. It prevents conflict resolution D. It converts commits into tags Correct Answer: B. It changes the identities and ancestry of commits Question 4Which operation is normally preferred for undoing a faulty commit on a public branch? A. git reset --hard B. git rebase -i C. git revert D. git reflog expire Correct Answer: C. git revert Question 5What does cherry-pick do? A. Copies an entire repository B. Applies a selected commit’s change as a new commit C. Deletes a selected commit permanently D. Renames a remote branch Correct Answer: B. Applies a selected commit’s change as a new commit Question 6Which reset mode moves the branch reference while leaving the index and working tree unchanged? A. --soft B. --mixed C. --hard D. --merge-only Correct Answer: A. --soft Question 7What is the main purpose of the reflog? A. To publish branches to a remote B. To record local reference movements for inspection and recovery C. To validate source-code syntax D. To encrypt commit objects Correct Answer: B. To record local reference movements for inspection and recovery Question 8After manually resolving a merge conflict, what must normally happen before completing the merge? A. The resolved files must be staged B. The remote must be deleted C. The branch must be rebased twice D. The reflog must be cleared Correct Answer: A. The resolved files must be staged Question 9Why is git push --force-with-lease safer than git push --force? A. It never rewrites history B. It checks that the remote is in the expected state C. It automatically resolves conflicts D. It creates a protected branch Correct Answer: B. It checks that the remote is in the expected state Question 10A team needs one defect fix on a maintenance branch but not the other features from the development branch. Which technique is most targeted? A. Cherry-pick B. Hard reset of the maintenance branch C. Delete the maintenance branch D. Rebase the entire repository Correct Answer: A. Cherry-pick
|