VIEW THIS AS

Auto mode follows the Route Engine until you choose a viewpoint.

YOU ARE HERE

ROUTE CHECK

CONNECTED TO

WHAT NEXT

Use the canonical route for this room, or HELP if you are unsure.

Why Mathematics? | Version Control, Commit Graphs, Hashes and Merging

Three learners review open books together at a classroom table, with stacks of textbooks, stationery and a whiteboard in the bright room.

Why Version Control Is a Mathematical System

Why is mathematics important in version control? A version-control system records changing project states, connects each state to its parent or parents, names content with hashes, compares sets of lines or objects, finds common ancestors and combines independent work. The familiar commands “commit,” “branch” and “merge” sit on top of directed graphs, partial orders, set operations, string algorithms and probability.

The importance of mathematics becomes clear when two branch names move without copying the project, a merge has two parents, a history search walks only reachable commits, or identical content is stored once. Version control is not merely a stack of numbered backups. It is a structured model of identity, ancestry and change.

This article uses Git because its official documentation describes these structures openly. Other version-control systems make different choices. Git itself has versions and configuration options, so examples explain durable concepts rather than claiming every command behaves identically in every repository. Version control also does not replace tested backups, access control or careful review.


Quick Reading Routes

  • Students: begin with snapshots, hashes, directed graphs and branches.
  • Parents: read collaboration, recovery, safety and learning guidance.
  • Teachers: use the ancestry, merge-base, set-difference and collision investigations.
  • Career explorers: connect this topic to software engineering, data science, design, documentation, research reproducibility and cybersecurity.

Practise in a new disposable repository containing no private data. Never rewrite or publish a shared history unless the repository owner and collaborators have agreed on the operation.


A Commit Is a Node, Not a Folder Copy

Snapshots represent project states

A commit records a project state together with metadata and parent references. Conceptually, it points to a tree describing names and content objects. Git can reuse unchanged objects rather than physically copying every byte for every commit.

This distinction matters. If a 100 MB project changes one small file, the next logical snapshot can represent the whole project without necessarily storing another independent 100 MB archive. Identity and reachability determine reuse.

Parents create directed edges

Draw each commit as a vertex. Draw an edge from a commit to each parent. Ordinary commits usually have one parent; an initial commit has none; a merge commit usually has more than one. The arrows point backward through history.

Git's glossary describes commit objects as forming a directed acyclic graph, or DAG. It is directed because parent relationships have a direction, and acyclic because following parents does not return to the same commit.

A topological order is not always one timeline

In a line A → B → C, the order is obvious. With branches, commits B and X may both descend from A without either descending from the other. They are incomparable in the ancestry partial order. Timestamps may suggest a display order, but they do not turn independent commits into parent and child.

This corrects the “history is a list” misconception. Many valid linearisations can display a DAG while respecting parent-before-child constraints. A log option chooses a view of structure; it does not rewrite the graph.


Content-Addressed Storage Uses Hash Functions

A digest names content

A hash function maps an input of arbitrary length to a fixed-length digest. Git object identifiers are computed from an object's type, length and content according to its object format. If content changes, the identifier is expected to change.

The name is content-derived rather than assigned from a central counter. This makes integrity checks and deduplication natural: an object with the same identifier is expected to have the same encoded content under the hash assumptions.

The pigeonhole principle guarantees possible collisions

There are more possible inputs than b-bit outputs, so some distinct inputs must share a digest. That is a mathematical certainty. Security depends on making a collision infeasible to find for the chosen function and threat model, not on claiming collisions are logically impossible.

For ideal uniformly random b-bit outputs, a specified second input matches one digest with probability 1/2^b. Across many randomly chosen objects, collision probability becomes noticeable around the square root of the output space because there are roughly n(n − 1)/2 pairs. This is the birthday effect.

Short names are prefixes

Interfaces often display an abbreviated object identifier. A prefix must be long enough to be unique within the repository's current object set. As more objects arrive, a previously unique short prefix might become ambiguous.

If hexadecimal digits are used, each digit carries four bits. Seven hex digits represent 28 bits and about 268 million possible prefixes, but distribution, adversaries and repository scale matter. Tools should resolve ambiguity rather than silently guess.

Hashes are not access control

Knowing or not knowing an identifier is not a substitute for authorisation. Repository permissions, authentication and hosting controls decide who may read or write. Hashes support identity and integrity within a system; they do not automatically encrypt content or prove who authored it.

A signed commit or tag adds a cryptographic statement tied to a key, but trust still depends on verifying the key and protecting it. One mechanism cannot carry every security property.


Trees Map Names to Objects

A directory-like hierarchy

Git tree objects associate names and modes with object identifiers. A root tree can point to blobs and other trees, forming a hierarchy. A commit points to a root tree, so the complete project snapshot is reachable by following references.

If two commits share an unchanged subtree, both can point to the same tree object. Only changed paths require new objects along the affected route. The graph shares structure while preserving immutable historical states.

Reachability defines what belongs to a snapshot

Starting from a commit, follow its tree and descendants. The set of reachable blobs and subtrees defines the recorded project state. Starting from branch tips and tags, following commit parents defines reachable history.

Garbage collection can eventually remove objects that are not reachable from retained references and are beyond recovery grace policies. “Not shown by a branch” and “physically gone” are different states, just as deleting a filename and overwriting storage are different in a file system.

Merkle-style propagation

If a file's content changes, its blob identifier changes. The containing tree's encoded content then changes, so its identifier changes, and this propagates toward the root. A commit pointing to the new root is therefore tied to the entire snapshot structure.

This does not mean every byte is rehashed during every later operation; stored objects and indexes help. The conceptual property is that references form an integrity-linked structure.


Branches Are Movable References

A branch name points to a commit

A branch is not a second physical copy of the repository. It is a named reference that normally points to a tip commit. Creating a branch adds a pointer; making a new commit advances the current branch pointer to the new node.

If `main` points to C and `feature` also starts at C, their histories are identical at that moment. A new feature commit D moves `feature` to D while `main` remains at C. The project states can now differ because the tips select different snapshots.

HEAD identifies the current position

Git uses HEAD to represent the checked-out branch or, in a detached state, a specific commit. The working tree and index provide additional mutable states. Confusing these layers causes many beginner errors: edited files are not automatically staged, staged changes are not automatically committed, and committed work is not automatically sent to a remote.

A useful state model lists four locations: working tree, index, local commit graph and remote-tracking knowledge. Each command moves information across particular boundaries.

Fast-forward is an ancestry test

If current tip C is an ancestor of target tip D, moving the branch pointer from C to D preserves all history without creating a new merge commit. This is a fast-forward. The condition is graph reachability, not whether files look similar.

If neither tip is an ancestor of the other, the histories diverged. Combining them requires a merge, rebase or another explicit decision. The graph tells the tool which case applies.


Sets Explain Revision Ranges

Reachable commits form sets

Let R(A) be the set containing commit A and all commits reachable by following parents. The commits reachable from B but not A are R(B) − R(A). Many history queries are set operations over reachability.

Suppose main reaches {A,B,C} and feature reaches {A,B,D,E}. Commits unique to feature are {D,E}; commits unique to main are {C}; common history is {A,B}. A command's range syntax and boundary rules determine which set is reported.

Symmetric difference shows either side

The symmetric difference between sets X and Y is (X − Y) ∪ (Y − X). It includes items unique to either side, excluding their intersection. For the example, the symmetric difference is {C,D,E}.

This is useful when reviewing divergence, but a log may also mark which side reaches each commit. Again, the mathematical set is separate from the chosen display order.

First-parent views simplify a mainline

At a merge commit, following only the first parent creates one selected chain through the DAG. The git-log documentation explains that `–first-parent` can give a better overview of the evolution of a topic or mainline by hiding some detail brought through merges.

This is a projection, not the deletion of other commits. Good visualisation deliberately omits detail while preserving the relationship needed for a question.


Merge Bases Find Shared Ancestry

A common ancestor is not always unique

For tips X and Y, a common ancestor is reachable from both. A merge base is a “best” common ancestor: one that is not an ancestor of another common ancestor. In a simple history, there is one obvious branch point. Criss-cross merges can yield more than one merge base.

Finding a merge base is a graph problem, not a filename comparison. Git's commit-graph documentation notes that graph walks support operations including history listing and merge-base calculation.

Three-way merge compares three states

A three-way merge considers the base B and two tips, ours O and theirs T. For each region, it asks how O differs from B and how T differs from B. If only one side changed a region, that change can often be applied. If both changed compatibly, both may be combined. Otherwise human judgement may be needed.

Without the base, the system cannot distinguish an unchanged side from a side that independently produced a value. The third state supplies causal context.

A tiny table example

Base has `colour=blue`. Ours changes it to `green`; theirs leaves it `blue`. The natural three-way result is `green` because only ours changed. If theirs changes it to `red`, both changed the same field differently, so an automatic tool should not invent an intention.

Text merge algorithms work with sequences and surrounding context, but semantic meaning can extend beyond lines. Two edits in different files can still conflict logically. A clean automatic merge must still be tested.


Diff Algorithms Compare Sequences

Longest common subsequences reveal alignment

Given two sequences, a longest common subsequence (LCS) is a longest sequence appearing in both in the same order, not necessarily contiguously. The LCS helps frame insertions and deletions.

For `ABCDEF` and `ABZDF`, one common subsequence is `ABDF`. The comparison can describe removing C and E, then inserting Z. Multiple optimal alignments can exist, so diff tools use algorithms and heuristics to produce useful output efficiently.

Dynamic programming has a cost

A classic LCS table for sequences of lengths m and n uses O(mn) cells, which is expensive for large files. Practical diff algorithms exploit structure and trade time, memory and output readability. A minimal edit script is not always the easiest for a human to review.

Mathematics helps articulate the objective. Are we minimising edit count, preserving moved blocks, grouping related lines or producing stable output? Different objectives can produce different legitimate diffs.

Lines are a chosen tokenisation

Most source diffs use lines, but a line is not the only unit. Word diffs, syntax-aware tools and binary formats use other tokens. Reformatting can make many lines appear changed even when program behaviour is intended to remain the same.

Review quality improves when formatting-only changes are separated from semantic changes. This is an information-design decision as much as an algorithmic one.


Merging Is Not Addition

Changes can commute or interfere

Two transformations commute if applying A then B gives the same result as B then A. Edits to independent files often commute. Two edits to the same configuration key may not. A merge attempts to combine transformations while preserving intended invariants.

Textual separation is evidence of independence, not proof. Changing a function name in one file and calling it from another can create a broken combination even if no line-level conflict appears.

Conflict resolution is a new decision

When a tool marks a conflict, the resolver should understand base, ours and theirs, then create a result that may differ from either side. Choosing all lines blindly can duplicate operations or violate syntax.

The resolved content should be tested, reviewed and committed as an explicit project state. Conflict markers are an invitation to reason, not a punishment.

Merge commits preserve topology

The official git-merge documentation shows a merge commit with two parents joining histories. The commit records the combined snapshot and the fact that two lines of development were reconciled.

A rebase can instead replay changes onto a new base, creating new commits with new identities. It may produce a simpler line but rewrites the selected history. Neither topology is universally best; team policy and published references matter.


Rebasing Changes Identity

Same patch does not mean same commit

A commit identifier includes more than the final file change: it reflects the tree, parents and metadata. Replaying a similar patch onto a different parent creates a different commit object and identifier.

This is why rebase is not merely moving a branch label. It constructs new nodes, then moves a reference. The old nodes may remain temporarily reachable through reflogs or other references, but collaborators pointing to the old graph now see divergence.

Coordinate before rewriting shared history

If a commit is private to one developer, rewriting it may be straightforward. If others have based work on it, rewriting creates duplicate-looking lines and reconciliation work. The cost grows with the number of dependent collaborators.

The graph model makes etiquette quantitative: each published descendant is another dependency. Team rules about protected branches and force pushes manage this coordination risk.

Force-with-lease is a condition

A guarded update can require the remote reference to equal the value the sender expects. In logical form: update only if current_remote = observed_remote. If someone else advanced the branch, the condition fails rather than overwriting unseen work.

This is an optimistic concurrency check, closely related to version fields in databases. It reduces one class of accidental overwrite but does not make every rewrite appropriate.


Commit-Graph Files Accelerate Graph Walks

Derived data can speed repeated queries

The object database contains enough information to reconstruct ancestry. A supplemental commit-graph file stores derived information that helps walks avoid repeatedly decompressing and parsing every commit. Git documents it as an acceleration structure, not a replacement for objects.

This resembles a database index. The source of truth remains, while an auxiliary structure trades storage and maintenance for faster queries. If disabled or rebuilt, the history still exists in the object database.

Generation numbers bound traversal

A generation number increases along parent-child relationships according to a documented rule. If a candidate's generation is too low or high for a search boundary, the walk can prune work. The number summarises some ancestry information without storing every reachable set explicitly.

Summaries are useful because full transitive reachability can be large. The design seeks a compact value that preserves a safe inequality for pruning.

Bloom filters help path history

Commit-graph data can include changed-path Bloom filters. A Bloom filter can say “definitely not present” or “possibly present.” False positives cause extra work; false negatives should not occur under correct construction for the represented set.

This connects to the earlier Why Mathematics? article on Bloom filters. A probabilistic index accelerates search while the underlying data confirms results.


Collaboration Is a Distributed-State Problem

A remote is another repository

Clones have their own object databases and references. Fetching transfers objects and updates remote-tracking references; it does not necessarily change the current branch or working files. Pushing asks another repository to update a reference under its policy.

There is no magical shared folder in the basic model. Participants exchange immutable objects and negotiate movable names. Network interruption and concurrent updates therefore require checks.

Non-fast-forward rejection protects unseen ancestry

If a remote branch has advanced to R and a proposed update points to P where R is not an ancestor of P, accepting it would make R no longer reachable from that branch. Hosts often reject the update unless an authorised force operation is used.

The rejection is a graph-safety rule. The user can fetch R, integrate it, then propose a tip that descends from both histories.

Distributed does not mean leaderless policy

The data model allows many repositories, but teams still choose authority: protected branches, review requirements, signing, release tags and access controls. Mathematics describes possible states; governance chooses acceptable transitions.

Good collaboration combines graph literacy with communication. A technically valid push can still be socially wrong if it bypasses review or exposes secrets.


Probability Helps Explain Hash Risk

The birthday approximation

For n uniformly random values in a space of size M, the probability of at least one collision is approximately 1 − exp(−n(n − 1)/(2M)) when n is small relative to M. The approximation shows why pair count grows quadratically.

It should not be used to claim real cryptographic safety by arithmetic alone. Hash design, known attacks, chosen-prefix threats, object-format protections and software validation matter. Use current official guidance for security decisions.

Accidental and adversarial models differ

An accidental model treats inputs as not chosen to cause a collision. An adversary deliberately searches for structure. A function adequate for a hash table may be unsuitable for security-sensitive object identity.

Always name the threat model. “One in 2^b” may describe a random preimage-style event, not the work needed for the most relevant collision attack.

Risk is more than probability

Expected harm combines likelihood and impact, but dependency and detection also matter. A compromised release tag can have far greater effect than a harmless local collision test. Controls include strong formats, signatures, review, restricted publishing and reproducible builds.

Numbers support a layered safety argument. They do not eliminate the need for secure processes.


A Complete Worked Example: Two Students Edit One Project

Build the graph

Both students begin at commit A. Mei creates commit B on `main`. Arjun creates commits C and D on `feature`, both descending from A. The graph has edges B → A, C → A and D → C. Neither B nor D is an ancestor of the other.

Reachable sets are R(B) = {A,B} and R(D) = {A,C,D}. Their intersection is {A}; A is the simple merge base. The symmetric difference is {B,C,D}.

Compare changes against the base

At A, a data file says `threshold=10`. Mei's B changes it to 12. Arjun's branch leaves that line unchanged but adds a chart file. A three-way merge sees one change to the threshold and an independent addition, so it can plausibly combine both.

If D had changed the threshold to 8, the same line would have two incompatible changes relative to A. The tool cannot know whether 8, 12 or a new value is intended. The students must discuss the requirement.

Create and validate the merge

They choose 12 after checking the specification, include the chart, run tests and create merge commit M with parents B and D. Now R(M) includes A, B, C, D and M. Both lines remain visible in the topology.

The merge does not prove the chart uses the new threshold correctly. They add a test that checks chart behaviour with threshold 12. Graph consistency and program correctness are related but separate.

Recover from a mistaken local reset

Later, a student moves a local branch pointer backward by mistake. The commits may still exist and be referenced by a reflog for a retention period. Recovery means finding the old identifier and moving or creating a safe reference before expiry.

This possibility is helpful, not a backup guarantee. Reflog scope and retention vary; remote copies and independent backups protect against other failures.


Common Misconceptions to Correct

“A branch copies the whole project”

A branch is normally a movable reference to a commit. Snapshots reuse immutable objects and shared history.

“Commit order is just timestamp order”

Parent edges define ancestry. Independent commits may be incomparable even if their timestamps can be sorted for display.

“A hash can never collide”

Finite outputs imply possible collisions. Security relies on making relevant attacks infeasible and using current protections, not mathematical impossibility.

“No conflict means the merge is correct”

Automatic merging checks textual structure. Logical, security or cross-file conflicts may remain. Test and review the result.

“Version control is a backup”

It records project history, but repositories can be deleted, corrupted or exposed. Maintain independent protected copies and verify restoration.

“Rebase only makes the graph look tidy”

Rebase creates new commits with different parents and identifiers. Rewriting published history affects collaborators.


How Students Can Build Transferable Skill

Draw the graph before using commands

Create six paper commits with arrows to parents. Add two branch labels, move one label after a commit, and form a merge with two parents. For each tip, list the reachable set.

Then predict whether an update is a fast-forward. Graph drawing turns command behaviour into consequences rather than memorised recipes.

Calculate a toy hash carefully

For learning only, map a string to the sum of character codes modulo 16. Find two different strings with the same result. This demonstrates the pigeonhole principle and collision handling.

Do not confuse the toy function with a secure hash. The exercise's purpose is to reveal why fixed-size summaries need explicit assumptions.

Simulate a three-way merge

Write a base paragraph, make one edit on each of two copies, then compare both with the base. Try disjoint edits, identical edits and conflicting edits. Explain why two-way comparison loses information.

Extend the exercise to a spreadsheet or design brief. Version-control reasoning applies wherever collaborative artefacts evolve, even when a tool stores binary files differently.

Measure repository questions

In a disposable repository, create branches and merges, then use log options to view topology and first-parent history. Predict each reachable set before running the command. Record Git's version and avoid force operations on shared remotes.

The goal is not command speed. It is matching a formal model to observed state.


Guidance for Parents and Teachers

Focus on explanation and recovery

Ask a learner to explain where an uncommitted change lives, what a branch points to, and how they would recover from an accidental local move. A student who can describe state boundaries is less likely to use destructive commands blindly.

Use small repositories with visible text files. Avoid placing passwords, personal data or assessed work in public hosting during experiments.

Separate algorithmic and social conflict

A merge conflict is a tool's signal that edits overlap under its model. A team disagreement concerns intended meaning. Students should learn to inspect evidence, communicate and test, not treat conflict markers as a contest to be won.

Assess claims with diagrams

Require a commit graph, reachable-set table and explanation of the merge base. A screenshot of a successful command is weaker evidence than a prediction that matches the result.

This encourages mathematical communication and makes copying commands less rewarding than understanding.


Mathematics Learning in Singapore

The MOE secondary mathematics syllabuses emphasise mathematical problem solving, reasoning, communication and algorithms. Version control offers concrete applications: sets model reachability, directed graphs model history, probability frames hash collisions, sequences support diffs, and logic constrains safe updates.

The official MOE Computing teaching and learning syllabus also discusses decomposing problems and algorithmic strategies. Version control supports computing projects, but this article does not claim it is an examination requirement for every learner.

SEAB states that the Singapore-Cambridge Secondary Education Certificate starts in 2027 with G1, G2 and G3 subjects; use the current SEC information page for cohort-sensitive terminology. Skills and pathways should be checked against the student's actual programme.


Did You Know?

Two branches can point to the same commit. Creating the second branch adds a name, not a duplicate project history.

A merge commit can have two parents, so “previous commit” is ambiguous unless the parent is specified. Graphs handle this naturally; a simple numbered list does not.

Git's commit-graph file is an index-like acceleration structure. The underlying object database still contains the information needed to walk history, much as a database table remains authoritative when an index is rebuilt.


Frequently Asked Questions

Is Git history a tree?

The commit history is generally a directed acyclic graph because merges allow a commit to have multiple parents. Individual tree objects represent snapshot directory structure.

Why does a rebased commit get a new identifier?

Its parent and often metadata change, so the encoded commit object changes. Content-addressed identity follows the whole object, not only the visible patch.

What is a merge base?

It is a best common ancestor used to compare how two tips changed from shared history. Some graph shapes can have more than one.

Does a clean merge mean tests are unnecessary?

No. Text can merge without detecting semantic, security or cross-file incompatibilities. Run relevant tests and review.

Can a short hash identify a commit forever?

A short prefix may be unique now and ambiguous later as the object set grows. Use the resolution provided by tools and full identifiers where durable precision matters.

Is Git suitable for every kind of large binary data?

Not automatically. Storage, diffing and collaboration patterns matter. Extensions or other systems may be more appropriate. Model the workload before choosing.

Does version-control skill guarantee a software job?

No. It is valuable collaborative infrastructure, but careers also require programming, testing, communication, domain knowledge and experience.


Useful Next Reading


Final Perspective

Version control shows how abstract mathematics supports human collaboration. Directed graphs preserve branching history, sets answer “what is reachable?”, hashes name immutable objects, sequence algorithms expose changes, and partial orders distinguish ancestry from mere clock time.

The most durable skill is not memorising a list of commands. It is asking: Which state am I changing? What does this reference point to? Which commits are reachable? What common ancestor supplies context? What safety condition protects another person's work?

Those questions make version control calmer and more transparent. They also demonstrate why mathematics matters: it gives a team a shared language for history, identity and change, so many people can build something together without pretending their work happened in one straight line.

Discover more from eduKate Singapore

Subscribe now to keep reading and get access to the full archive.

Continue reading