SECTION 02 / 6

Module 2 · Version Control Systems

8 min read
On this page 24 headings

Learning goals: How Git records history, how repositories communicate and how teams use branches, merging and rebasing.

Why Teams Need Version History

When different developers change the same application, an accidental defect can enter the code. Version history records earlier states so the team can understand what changed and can recover a stable version when necessary. This does not mean every new change is automatically correct.

Figure 9. Why Teams Need Version History.
Figure 9. Why Teams Need Version History.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Keep history so mistakes can be investigated and earlier versions recovered.

Client-Specific Versions

A software product may share common features across customers while including some customer-specific work. Version control helps developers manage different lines of development and trace which changes belong where. Without a clear strategy, maintaining several versions can become confusing.

Figure 10. Client-Specific Versions.
Figure 10. Client-Specific Versions.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Share common work where appropriate and track customer-specific changes carefully.

What Version Control Tracks

In software engineering, version control systems fall under software configuration management. They track and manage changes over time through branching, merging and commits; maintain different revisions with labels, e.g. 1.2, 1.3, 2.0, 3.2.1; and maintain change history including who changed what. Additional features (not exhaustive) include comparing revisions, integrated code-review tools, issue-tracking tools and collaborative development.

Figure 11. What Version Control Tracks.
Figure 11. What Version Control Tracks.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: History is more useful when changes and commit messages are clear.

Centralised vs Distributed VCS

Centralised VCS: a central repository on a server that everybody shares; a client–server model. Check out the whole or part of the repository → make changes → push back to the server. Examples: Perforce, SVN. It is highly dependent on the server: if anything goes wrong, development halts until the server is up again; the entire history can be lost if no backups are configured. Distributed VCS: the entire repository, with full change history, is mirrored locally; central hosting is possible but there is no complete dependency on it. Git is one of the most popular distributed VCS.

Figure 12. Centralised vs Distributed VCS.
Figure 12. Centralised vs Distributed VCS.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Git is distributed: local repositories contain commit history.

Why are version control systems important?

Version control increases productivity; improves communication and collaboration; saves space on multiple revisions through diffs/snapshots; and improves efficiency even as teams scale. Nowadays the question is not whether to use one, but which one to use.

Git and ways to use it

Git is free and open source, originally authored by Linus Torvalds in 2005 for development of the Linux kernel. Its focus is speed (nearly every operation is local), data integrity (the entire repository is mirrored, with multiple copies, making data very hard to lose), and working on multiple tasks simultaneously through multiple branches and parallel development.

Using Git

Use the command line (install git), use Git with IDEs, or use the GitHub portal through a GUI.

Three States of a Git File

A Git file can be modified in the working directory, staged (marked) with git add, and committed to local history with git commit. Only staged files are committed, even if more files were modified.

Figure 13. Three States of a Git File.
Figure 13. Three States of a Git File.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Working Directory → Staging Area → Local Repository.

Local Repository and Remote Repository

The local repository belongs to a developer's computer; the remote repository is a shared location used for collaboration. git push publishes suitable local commits to the remote, while git pull brings remote changes into the current local branch and integrates them. Pulling may require resolving conflicts.

Figure 14. Local Repository and Remote Repository.
Figure 14. Local Repository and Remote Repository.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Local and remote histories communicate, but are not automatically identical.

Start a Repository: Init or Clone

Use git init when you have a new project folder and want Git to begin tracking it. Use git clone when an existing repository already lives elsewhere and you want a local copy. Both can lead to a local Git repository, but their starting situations are different.

Figure 15. Start a Repository: Init or Clone.
Figure 15. Start a Repository: Init or Clone.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: New folder: git init. Existing repository: git clone.

Git Add, Commit, Push

A typical publishing sequence starts with files in the working directory. git add selects the changed content for staging; git commit records a local snapshot; git push sends appropriate local commits to a remote repository. The middle step matters: staging and committing are not the same as publishing.

Figure 16. Git Add, Commit, Push.
Figure 16. Git Add, Commit, Push.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: git add → git commit → git push; each command has a distinct purpose.

Git Pull Updates Local Work

Imagine Developer A pushes a change. Developer B's existing local copy does not automatically update. When B runs git pull, Git obtains and integrates remote updates into the current local branch. Git may report a conflict if B has incompatible local work.

Figure 17. Git Pull Updates Local Work.
Figure 17. Git Pull Updates Local Work.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Pull before collaborating on shared code, and read any conflict message carefully.

More Git Commands

git status reports file states. git diff shows changes between commits, a commit and the working tree, etc. git reset HEAD <filename> unstages the file. The lecture describes git checkout <filename> as undoing changes that are committed but not yet pushed to remote. git log shows commit history.

Figure 18. More Git Commands.
Figure 18. More Git Commands.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Inspect the state before modifying history or the staging area.

Branches Let Developers Work Independently

A branch is a pointer to a commit/snapshot; the default branch in the lecture is master, created at initialization. A developer can switch branches on the fly. git branch feature1 creates a branch; git branch lists local branches; git checkout <branch> switches; git checkout -b <branch> creates the branch if it does not exist.

Figure 19. Git Branching.
Figure 19. Git Branching.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Branches separate ongoing work until the changes are deliberately integrated.

Merge Combines Work

A merge combines work from branches. Git does a three-way merge if there are no conflicts; else resolve the conflicts and then merge.

Figure 20. Merge Combines Work.
Figure 20. Merge Combines Work.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Run git merge feature1 while checked out on the destination branch.

Urgent Issue Interrupts a Feature

Sometimes a high-priority bug needs attention before a planned feature is done. Rather than mixing unfinished feature code into an emergency fix, create a separate issueP branch from the stable base, fix and test the bug, merge the fix, and return to feature1. The feature work stays on its own branch.

Figure 21. Urgent Issue Interrupts a Feature.
Figure 21. Urgent Issue Interrupts a Feature.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: An urgent fix should not force unfinished feature code into production.

Feature Branch Starts at C2

In the lecture example, the existing history is C0 → C1 → C2, and master points to C2. Creating feature1 at that moment makes feature1 point to the same C2. No new commit is required just to create the branch name; the two branches separate when new commits are made.

Figure 22. Feature Branch Starts at C2.
Figure 22. Feature Branch Starts at C2.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: After branching, master and feature1 can initially point to the same commit.

Feature Commit C3 and Priority Commit C4

Next, the feature branch receives commit C3, while the urgent issue branch receives a separate commit C4. Both descend from the common earlier work C2. The C3 feature work and the C4 urgent fix are independent until the team chooses to combine them.

Figure 23. Feature Commit C3 and Priority Commit C4.
Figure 23. Feature Commit C3 and Priority Commit C4.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: C3 and C4 are siblings in the original branch history, not consecutive commits.

Merge Priority Fix Before Feature

git checkout master; git merge issueP; git branch -d issueP. The master pointer moves from C2 to C4. Then master is ahead of feature1 by one commit.

Figure 24. Merge issueP into master.
Figure 24. Merge issueP into master.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Merge issueP into master, then delete issueP.

Merge Feature After Priority Fix

git checkout master; git merge feature1. Git does a three-way merge if there are no conflicts; else resolve the conflicts and then merge.

Figure 25. Merge feature1 into master.
Figure 25. Merge feature1 into master.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Merge feature1 into master after incorporating the priority fix.

Merge Conflicts: Resolve, Then Merge

If a file x.py was changed in issueP (C4) and also in feature1 (C3), Git does not know which changes to keep; you are asked to resolve the conflicts if Git cannot.

Figure 26. Merge Conflict: Same File Changed in Both.
Figure 26. Merge Conflict: Same File Changed in Both.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Resolve the conflicts, then merge.

Rebase: Why Feature Needs fun1()

feature1 needs fun1(), but fun1() was added on master after feature1 branched. Rebase incorporates changes from one branch to another, changing the base commit of feature1 so fun1 is available to test locally. Conflicts can occur while rebasing; resolve them to complete the rebase.

Figure 27. Why Rebase? feature1 Needs fun1().
Figure 27. Why Rebase? feature1 Needs fun1().
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: Rebase changes the base commit of feature1.

Git Rebase Replays Commits

git checkout feature1; git rebase master → feature1 is at C5 on top of C4. Then merge feature1 into master, after which both point to C5.

Figure 28. Git Rebase Replays Commits.
Figure 28. Git Rebase Replays Commits.
Open image ↗
Illustration: Module 2 · Version Control Systems

Remember: After rebase, feature1 points to C5; after the subsequent merge, master also points to C5.

Quick revision and self-check

Question: Does git commit push changes to the remote?

Answer: No. Commit saves local history; push publishes suitable commits.

Question: Where does feature1 point immediately after it is created from C2?

Answer: At C2, the same starting commit as master.

Question: After rebasing feature1 on C4, does master automatically move to the replayed commit?

Answer: No. Only the feature branch moves in the illustrated rebase.

For more details, see the book at git-scm.com.

YOUR STUDY PROGRESS

Finished this section? Save your progress.

Back to top ↑