Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Git & GitHub  Module 1 – Getting started with Git

What version control is and why Git won

What a version control system records, why Git became the standard, how it differs from GitHub and Subversion, and why every clone holds the full history.

  • Beginner
  • 20 minutes
  • Examples run with git 2.54.0, Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free lesson, Pro answers: 20 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Explain what a version control system records and why teams rely on one
  • Distinguish Git, a distributed version control system, from GitHub, a hosting and collaboration service
  • Contrast centralised systems such as Subversion with Git's full-history local clones
  • Describe Git's snapshot model and why commits are cheap to create and compare
What you’ll learn

What you will learn

  • Explain what a version control system records and why teams rely on one
  • Distinguish Git, a distributed version control system, from GitHub, a hosting and collaboration service
  • Contrast centralised systems such as Subversion with Git's full-history local clones
  • Describe Git's snapshot model and why commits are cheap to create and compare
On this page

Version control is software that keeps a record of every saved state of a project: which files changed, who changed them, when, and the reason they gave. With that record you can compare any two states, find the change that broke something and go back to an earlier version, and several people can work on the same files without overwriting each other’s work. Git is the version control system that most developers use, and it won on its design. Every copy of a project holds the complete history, so reading history, comparing versions, branching and recording changes are fast and need no server. It was built for one of the largest projects there is, the Linux kernel. It is open source. And hosting services such as GitHub were built around it. This lesson shows each of those points with real Git sessions you can run yourself.

What version control records

Most people start with copies. A lab report goes through three versions and ends up as three files:

Three copies, then the same three versions as commits Python · history.py
from gitsession import session

session(r"""
# The old way: a new copy of the file for every version
mkdir report-copies
cd report-copies
printf 'Lab report\nResult: 9.8 m/s2\n' > report_final.txt
printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.04 m/s2\n' > report_final_v2.txt
printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.02 m/s2\nSigned: Asha\n' > report_final_REALLY.txt
ls
cd ..
# With Git: one file and three commits (the next lesson explains these three settings)
git config set --global user.name "Asha Rao"
git config set --global user.email "asha@example.com"
git config set --global init.defaultBranch main
git init -q report
cd report
printf 'Lab report\nResult: 9.8 m/s2\n' > report.txt
git add report.txt
git commit -q -m "Record the measured value"
printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.04 m/s2\n' > report.txt
git commit -q -am "Round to two decimals and add the uncertainty"
printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.02 m/s2\nSigned: Asha\n' > report.txt
git commit -q -am "Halve the uncertainty after a second run, and sign"
git log --format='%h %an: %s'
git diff HEAD~2 HEAD
""")

Output

# The old way: a new copy of the file for every version
$ mkdir report-copies
$ cd report-copies
$ printf 'Lab report\nResult: 9.8 m/s2\n' > report_final.txt
$ printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.04 m/s2\n' > report_final_v2.txt
$ printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.02 m/s2\nSigned: Asha\n' > report_final_REALLY.txt
$ ls
report_final.txt
report_final_REALLY.txt
report_final_v2.txt
$ cd ..
# With Git: one file and three commits (the next lesson explains these three settings)
$ git config set --global user.name "Asha Rao"
$ git config set --global user.email "asha@example.com"
$ git config set --global init.defaultBranch main
$ git init -q report
$ cd report
$ printf 'Lab report\nResult: 9.8 m/s2\n' > report.txt
$ git add report.txt
$ git commit -q -m "Record the measured value"
$ printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.04 m/s2\n' > report.txt
$ git commit -q -am "Round to two decimals and add the uncertainty"
$ printf 'Lab report\nResult: 9.81 m/s2\nUncertainty: 0.02 m/s2\nSigned: Asha\n' > report.txt
$ git commit -q -am "Halve the uncertainty after a second run, and sign"
$ git log --format='%h %an: %s'
cfae588 Asha Rao: Halve the uncertainty after a second run, and sign
0b13e80 Asha Rao: Round to two decimals and add the uncertainty
3d5a557 Asha Rao: Record the measured value
$ git diff HEAD~2 HEAD
diff --git a/report.txt b/report.txt
index 901377e..773a442 100644
--- a/report.txt
+++ b/report.txt
@@ -1,2 +1,4 @@
 Lab report
-Result: 9.8 m/s2
+Result: 9.81 m/s2
+Uncertainty: 0.02 m/s2
+Signed: Asha

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 history.py

The copies hold the same text as the commits, but that is all they hold. Nothing says who wrote each version, why it changed, or which one is really the latest; the names are guesses, and “REALLY” sorts before “v2”. The repository answers those questions. git log lists one line per commit: a short form of its ID (cfae588), the author and the message that says why the change was made. Each commit also records the time it was made. git diff HEAD~2 HEAD compares the first version with the latest, line by line: a minus sign marks a line that went, a plus sign a line that came in. HEAD is the commit you are on, and HEAD~2 the one two steps before it.

A commit is more than a save. Saving writes one file to disk and keeps no trace of the version before. A commit records the whole project as it was, with a name, a time, a message and a link to the commit before it, its parent, and it stays in the history after you change the files again.

Snapshots, not lists of changes

A commit does not store a list of edits. It points to a tree, a snapshot of every file in the project at that moment, and each file’s content is stored as a blob. This session makes two commits and then prints the tree of each, using git cat-file -p, which shows any stored object:

The tree of two commits, and the commit itself Python · snapshots.py
from gitsession import session

session(r"""
git config set --global user.name "Asha Rao"
git config set --global user.email "asha@example.com"
git config set --global init.defaultBranch main
git init -q report
cd report
printf 'Lab report\nResult: 9.8 m/s2\n' > report.txt
printf 'trial,seconds\n1,0.64\n2,0.63\n' > readings.csv
git add report.txt readings.csv
git commit -q -m "Record the measured value"
printf 'Lab report\nResult: 9.81 m/s2\n' > report.txt
git commit -q -am "Round to two decimals"
# Each commit's snapshot is a tree: one line per file, with the ID of its content
git cat-file -p HEAD~1^{tree}
git cat-file -p HEAD^{tree}
# The commit itself: its tree, its parent, who, when (seconds since 1970) and why
git cat-file -p HEAD
""")

Output

$ git config set --global user.name "Asha Rao"
$ git config set --global user.email "asha@example.com"
$ git config set --global init.defaultBranch main
$ git init -q report
$ cd report
$ printf 'Lab report\nResult: 9.8 m/s2\n' > report.txt
$ printf 'trial,seconds\n1,0.64\n2,0.63\n' > readings.csv
$ git add report.txt readings.csv
$ git commit -q -m "Record the measured value"
$ printf 'Lab report\nResult: 9.81 m/s2\n' > report.txt
$ git commit -q -am "Round to two decimals"
# Each commit's snapshot is a tree: one line per file, with the ID of its content
$ git cat-file -p HEAD~1^{tree}
100644 blob f8044c612e2c4e2cd70b2fd89e1ebbf8fdeb677b	readings.csv
100644 blob 901377ec5fb27535191b6525d9fab5986e439abf	report.txt
$ git cat-file -p HEAD^{tree}
100644 blob f8044c612e2c4e2cd70b2fd89e1ebbf8fdeb677b	readings.csv
100644 blob b1ae2ebbfde0ebe742baceb20a2beac146e18f0b	report.txt
# The commit itself: its tree, its parent, who, when (seconds since 1970) and why
$ git cat-file -p HEAD
tree a053a0f889e2b7cdb7663f3ff5639d75dd21b982
parent cfa7b135cdee2975ab66cc5b6a036e29b10251f8
author Asha Rao <asha@example.com> 1767240000 +0530
committer Asha Rao <asha@example.com> 1767240000 +0530

Round to two decimals

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 snapshots.py

Each line of a tree gives a file’s mode (100644 is an ordinary file), the object type, the ID of the content and the file name. report.txt changed, so the second tree names a new blob, b1ae2eb…. readings.csv did not change, and both trees name the same blob, f8044c6…, which Git stored only once. The commit at the end records exactly what this lesson started with: the tree, the parent, the author and committer, the time as seconds since 1970 with the time zone (+0530 is India’s), and the message.

Two commits, each pointing to a tree that lists every file; the unchanged readings.csv is one blob that both trees share.Commit 2Round to two decimalsCommit 1 (cfa7b13)Record the measured valueTree a053a0fsnapshot of commit 2Treesnapshot of commit 1report.txtblob b1ae2ebreport.txtblob 901377ereadings.csvblob f8044c6(stored once)parent

Two snapshots that share an unchanged file

Text description of the diagram

The diagram shows the two commits of the snapshots session and what each one points to.

  1. Commit 2, "Round to two decimals", points to its parent, commit 1 (cfa7b13), "Record the measured value".
  2. Each commit points to one tree, the snapshot of the whole project at that commit: tree a053a0f for commit 2, and a tree of its own for commit 1.
  3. Commit 1's tree lists report.txt as blob 901377e and readings.csv as blob f8044c6.
  4. Commit 2's tree lists report.txt as a new blob, b1ae2eb, because the file changed, and readings.csv as the same blob f8044c6, because it did not.

So the second snapshot is complete, yet only the changed file was stored again; the unchanged file is stored once and named by both trees.

Git’s manual on its data model is explicit that commits carry no diffs. git show and git diff work one out from two snapshots each time you run them. Snapshots are still cheap, because an unchanged file costs nothing new: the manual’s own example is a commit that changes 2 files in a repository of 1,000, which adds 2 blobs and reuses the IDs of the other 998.

Why the same content always gets the same ID

An object’s ID is a hash of its type and its content. For a file, Git hashes a short header, the word blob and the size in bytes, followed by the bytes themselves, with SHA-1. This Python program computes the IDs of the three file contents above without using Git at all:

Git's blob IDs, computed by hand Python · hashing/blob_ids.py
import hashlib


def blob_id(text):
    """The ID Git gives a file with this content: the SHA-1 of a short header and the file's bytes."""
    data = text.encode("utf-8")
    header = f"blob {len(data)}\0".encode("ascii")
    return hashlib.sha1(header + data).hexdigest()


print("report.txt, first version: ", blob_id("Lab report\nResult: 9.8 m/s2\n"))
print("report.txt, second version:", blob_id("Lab report\nResult: 9.81 m/s2\n"))
print("readings.csv, both times:  ", blob_id("trial,seconds\n1,0.64\n2,0.63\n"))

Output

report.txt, first version:  901377ec5fb27535191b6525d9fab5986e439abf
report.txt, second version: b1ae2ebbfde0ebe742baceb20a2beac146e18f0b
readings.csv, both times:   f8044c612e2c4e2cd70b2fd89e1ebbf8fdeb677b

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 blob_ids.py

They are the IDs Git printed in the trees. The same content gets the same ID on any computer, which is how two snapshots share an unchanged file, and how Git can tell from the IDs alone that readings.csv did not change between two commits, without reading it. Commits have IDs made the same way, from the tree, the parents, the author, the committer, the times and the message. That is why the first commit of the first session and the first commit of the clone session below both have the ID 3d5a557: same file, same name, same time, same message. Your own commits will get other IDs, because your name and your time differ.

Centralised and distributed version control

For many years the standard was a centralised system such as CVS or Subversion. One server holds the repository, the only complete history; each person’s working copy holds one version of the files, and older versions are fetched from the server when someone asks for them. Recording a change means sending it to the server.

Git is distributed. A clone is a complete repository: every commit, every branch and the whole history, in the .git folder next to your files. Reading history, comparing any two versions, making a branch and committing all happen on your own computer. A shared repository is only the place a team agrees to exchange commits.

Subversion: a server with the only full history and working copies of one version. Git: clones that each hold the full history.Centralised, such as SubversionDistributed: GitServerthe only full historyWorking copyone versionWorking copyone versionShared repositoryfull history, optionalClonefull historyClonefull historyupdate, commitupdate, commitfetch, pushfetch, push

Where the history lives

Text description of the diagram

The diagram has two panels, one above the other.

  1. Centralised, such as Subversion: one server holds the only full history. Two working copies are connected to it; each holds one version of the files. A working copy sends commits to the server and gets updates from it, so both need the server.
  2. Distributed, Git: two clones and a shared repository each hold the full history. The clones fetch from and push to the shared repository, but they can do everything else on their own, and the shared repository is optional: it is only the place the team agrees to exchange commits.

Here Ravi clones Asha’s repository, works on his own copy, and then sends his commit back. The “server” is just another folder on the same computer: to Git, it is simply another repository.

Clone, work alone, then share Python · clone_and_share.py
from gitsession import session

session(r"""
git config set --global user.name "Asha Rao"
git config set --global user.email "asha@example.com"
git config set --global init.defaultBranch main
git init -q report
cd report
printf 'Lab report\nResult: 9.8 m/s2\n' > report.txt
git add report.txt
git commit -q -m "Record the measured value"
cd ..
# Ravi clones Asha's repository: the clone holds every commit
git clone -q report ravi-report
cd ravi-report
git config set user.name "Ravi Kumar"
git config set user.email "ravi@example.com"
git log --format='%h %an: %s'
# Ravi works on his own copy: a branch, a commit, a comparison
git switch -q -c conclusion
printf 'Conclusion: matches the expected 9.81 within the uncertainty\n' >> report.txt
git commit -q -am "Add the conclusion"
git diff --stat main conclusion
# Only commands such as push and fetch talk to another repository: here, a folder
git push -q origin conclusion
cd ../report
git log --format='%h %an: %s' conclusion
""")

Output

$ git config set --global user.name "Asha Rao"
$ git config set --global user.email "asha@example.com"
$ git config set --global init.defaultBranch main
$ git init -q report
$ cd report
$ printf 'Lab report\nResult: 9.8 m/s2\n' > report.txt
$ git add report.txt
$ git commit -q -m "Record the measured value"
$ cd ..
# Ravi clones Asha's repository: the clone holds every commit
$ git clone -q report ravi-report
$ cd ravi-report
$ git config set user.name "Ravi Kumar"
$ git config set user.email "ravi@example.com"
$ git log --format='%h %an: %s'
3d5a557 Asha Rao: Record the measured value
# Ravi works on his own copy: a branch, a commit, a comparison
$ git switch -q -c conclusion
$ printf 'Conclusion: matches the expected 9.81 within the uncertainty\n' >> report.txt
$ git commit -q -am "Add the conclusion"
$ git diff --stat main conclusion
 report.txt | 1 +
 1 file changed, 1 insertion(+)
# Only commands such as push and fetch talk to another repository: here, a folder
$ git push -q origin conclusion
$ cd ../report
$ git log --format='%h %an: %s' conclusion
4186172 Ravi Kumar: Add the conclusion
3d5a557 Asha Rao: Record the measured value

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 clone_and_share.py

The clone arrived with Asha’s commit, and everything Ravi did next, the branch, the commit and the comparison, touched only his own repository. Only git push reached another repository. That is why Git keeps working on a train with no network. It is also why a clone can replace a lost server: the Git book on git-scm.com calls each clone a full backup.

Subversion or Git?
Criterion SubversionGit
Full history On the serverIn every clone
Older versions From the serverIn your clone
Commits Need the serverWork offline
Server lost History is lostAny clone has it
When to choose Files with locksMost projects

Files with locks are the one case in the table where Subversion fits better. No tool can merge two edited versions of an image, so Subversion lets one person lock such a file while editing it, and nobody else’s work on it is wasted.

Git and GitHub are not the same thing

Git is the program. It runs on your computer, keeps the history in the .git folder, works without an internet connection, and is open-source software under the GNU General Public License, version 2. GitHub is a service that hosts Git repositories online and adds tools for working together around them: pull requests to propose and discuss changes, issues to plan work, and Actions to run tests and other jobs automatically. GitHub’s own documentation describes it as built on Git.

Git or GitHub?
Criterion GitGitHub
What it is Version controlA hosting service
Where it runs Your computerGitHub’s servers
Needs an account NoYes
Works offline YesNo
Adds Commits, branchesPull requests, issues
When to choose AlwaysSharing online

GitHub is one host among several: GitLab, Bitbucket and Codeberg host Git repositories too, and a company can run its own Git server. The Git half of this track works with all of them; the lessons about pull requests, reviews and Actions use GitHub.

Not affiliated

Based on public information about GitHub. MySmartCoPilot is not affiliated with GitHub, and GitHub’s real features may differ from what this lesson describes.

Why Git won

Git was started in 2005 by the Linux kernel community, in particular Linus Torvalds, after the kernel lost its no-cost licence for BitKeeper, the system it had used since 2002. The Git book on git-scm.com lists what they wanted from the new tool: speed, a simple design, strong support for thousands of parallel branches, a fully distributed model, and the ability to handle a project the size of the kernel. Snapshots with content IDs deliver much of that: a commit adds only what changed, and a branch is cheap because it is just a name for a commit.

The rest followed from its open-source licence and from the services built around it. In Stack Overflow’s 2018 developer survey, 87.2 % of the 74,298 people who answered the question used Git, 16.1 % Subversion and 3.6 % Mercurial, the other distributed system of the time. Two years later, Bitbucket stopped hosting Mercurial repositories, after the share of its new users who chose Mercurial had fallen below 1 %.

What changes in Git 3.0

The Git project has announced Git 3.0, a release with new defaults for new repositories: SHA-256 instead of SHA-1 for object IDs, a new format for storing references called reftable, and main as the name of the first branch. It has set no release date, and existing repositories keep working: SHA-1 repositories are not being deprecated. The newest release is Git 2.56.0, and the examples of this track run on Git 2.54.0; a lesson says so when something depends on the version.

Three misconceptions

  • “Git stores diffs.” It stores snapshots and computes diffs when you ask. Inside the compressed pack files it makes for storage and transfer, Git may store an object as a difference from another one, but that is compression, invisible to every command you use.
  • “GitHub is Git.” GitHub is a service that hosts Git repositories. You can use Git all your life without GitHub, and the history in your clone is the same either way.
  • “Committing is saving.” Saving writes a file. A commit records a snapshot of the whole project, with a message, an author, a time and its parent, and it stays in the history.

Run the sessions yourself

Each session on this page is a short Python program that runs real Git commands one at a time and prints each one after a $, followed by what Git printed. You can follow along by typing the commands into a terminal in a new, empty folder, but leave out the git config lines: with --global they would replace your own settings, which the next lesson sets up properly. Your commit IDs will differ, because they depend on your name and the time.

To replay a session exactly on macOS or Linux, install Git (the next lesson shows how) and Python 3, put gitsession.py in the same folder as the session file and run, for example, python3 history.py. The helper starts every session in a new, empty folder called learner, which it also uses as the home folder, so the git config lines change only that folder and your own settings stay as they are; it also fixes the commit time, so your IDs match the ones on this page.

gitsession.py: the helper the sessions use Python · gitsession.py
"""Plays a terminal session with real Git: each command is printed after "$ ", then everything it printed.

The session runs in a new, empty folder called learner/, which is also its home folder, so your own Git settings
change nothing, and GIT_CONFIG_NOSYSTEM=1 makes Git skip the computer's system-wide settings file too. Git never
looks for a repository above that folder, so a session cannot touch a repository you run it from. In the output,
"~" stands for that folder. Commit times are fixed, because a commit's ID covers the time it was made: with the
same files, message, name and time, every run makes the same commit IDs.

Each line of a script is one /bin/sh command (macOS and Linux), except "cd", which the session does itself. A line
that starts with "# " is printed as a comment. A command written as "! command" is meant to fail: its exit status
is printed and the session goes on. Any other command that fails stops the session with exit status 1.
"""

import os
import shutil
import subprocess
import sys
from pathlib import Path

HOME = Path("learner").resolve()
# One fixed moment in Git's own date format: seconds since 1970, then the time zone (India, UTC+05:30).
FIXED_TIME = "@1767240000 +0530"


def _environment():
    # Git's own folder comes first, so every command runs that Git directly (on macOS, /usr/bin/git is a small
    # launcher that looks Git up again on every call).
    git_folder = subprocess.run(["git", "--exec-path"], capture_output=True, text=True, check=True).stdout.strip()
    env = {
        "PATH": os.pathsep.join([git_folder, os.environ.get("PATH", "/usr/bin:/bin")]),
        "HOME": str(HOME),
        "XDG_CONFIG_HOME": str(HOME / ".config"),
        "GIT_CONFIG_NOSYSTEM": "1",
        "GIT_CEILING_DIRECTORIES": str(HOME.parent),
        "GIT_AUTHOR_DATE": FIXED_TIME,
        "GIT_COMMITTER_DATE": FIXED_TIME,
        "LANG": "C",
        "LC_ALL": "C",
        "TERM": "dumb",
    }
    if "TMPDIR" in os.environ:
        env["TMPDIR"] = os.environ["TMPDIR"]
    return env


def _with_tilde(text):
    """Writes the home folder as "~", however the operating system spells its path."""
    for spelling in sorted({str(HOME), os.path.realpath(HOME)}, key=len, reverse=True):
        text = text.replace(spelling, "~")
    return text


def session(script):
    """Runs the script's commands one by one, starting in an empty home folder."""
    shutil.rmtree(HOME, ignore_errors=True)
    HOME.mkdir()
    env = _environment()
    folder = HOME
    for line in script.strip().splitlines():
        command = line.strip()
        if not command:
            continue
        if command.startswith("# "):
            print(command)
            continue
        meant_to_fail = command.startswith("! ")
        if meant_to_fail:
            command = command[2:]
        print("$", command)
        if command.startswith("cd "):
            folder = (folder / command[3:].strip()).resolve()
            continue
        done = subprocess.run(command, shell=True, cwd=folder, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
        print(_with_tilde(done.stdout), end="")
        if done.returncode != 0:
            print(f"[exit status {done.returncode}]")
            if not meant_to_fail:
                sys.exit(1)
        elif meant_to_fail:
            sys.exit(f"{command} was meant to fail, but it worked")

Check yourself

6 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 6 Which of these does Git itself do, on your computer, with no hosting service involved?

    Choose every answer that is right.

    Show the answer to question 1

    Answer:

    • Create a branch to try an idea
    • Compare any two versions of a file from the history
    • Record a commit with your name and a message

    Commits, comparisons and branches are Git's own work and happen in the .git folder on your computer. Pull requests and issues are features of hosting services such as GitHub, GitLab or Bitbucket, built around Git repositories; Git has no command for either.

  2. Question 2 of 6 You are on a train with no network, working in a clone of your team's repository. Which commands still work?

    Choose every answer that is right.

    Show the answer to question 2

    Answer:

    • git log, to read the history
    • git commit, to record your work
    • git diff, to compare your changes with the last commit

    A clone holds every commit, so reading history, comparing and committing touch only your own repository. Only commands that talk to another repository, such as push, fetch, pull and clone, need to reach it. Your commits wait in your clone and are pushed when you are back online.

  3. Question 3 of 6 A repository has 400 files. You change the content of 3 of them, each in a different way, and commit. How many new blobs does the commit add?

    Type a number.

    Show the answer to question 3

    Answer: 3

    A blob holds one file's content. The 3 changed files have new content, so they get 3 new blobs; the other 397 files keep their old blob IDs, and the new snapshot simply names them again. Git also writes a new tree for the snapshot, but that is a tree, not a blob.

  4. Question 4 of 6 You run git show on a commit and see a diff of what it changed. Where does that diff come from?

    Choose one answer.

    Show the answer to question 4

    Answer: Git compares the commit's snapshot with its parent's when you ask

    A commit stores a snapshot (a tree), not a diff. Git's data model says so directly: when you show a commit, Git calculates the difference from its parent on the fly. That is also why you can compare any two commits, not only neighbours.

  5. Question 5 of 6 Two people on different computers make a commit with the same files, the same parent, the same name and email, the same time and the same message. What can you say about the two commit IDs?

    Choose one answer.

    Show the answer to question 5

    Answer: They are the same, because the ID is a hash of exactly those details

    An object's ID is a hash of its type and content. A commit's content is its tree, its parents, the author and committer with their times, and the message, so identical details give an identical ID. The first commits of two sessions on this page share the ID 3d5a557 for this reason.

  6. Question 6 of 6 In a centralised system such as Subversion, what does a working copy on your computer hold?

    Choose one answer.

    Show the answer to question 6

    Answer: One version of the files; older versions come from the server when you ask for them

    In Subversion the repository, with the whole history, lives on the server, and a working copy is a local copy of one version. Asking for an older version means asking the server, and so does committing. A Git clone, by contrast, carries every commit.

Interview questions

What is the difference between Git and GitHub?

Git is a version control program. It runs on your computer, records a project’s history as commits in the .git folder, and needs no network or account except to exchange commits with another repository. It is open-source software under the GNU GPL, version 2. GitHub is a hosting service built on Git: it keeps Git repositories on its servers and adds collaboration features such as pull requests, issues, code review and Actions. A repository on GitHub is an ordinary Git repository, so you can clone it, work offline and push back, and the same history can also live on GitLab, Bitbucket or a team’s own server. In short, Git is the tool and GitHub is one place to share what it records: a team can use Git without GitHub, but not GitHub without Git.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    A teammate says Git saves only the changes between versions, so checking out an old commit means replaying every change since the first one. Is that right? Explain what Git actually stores, and how you would show it on a real repository.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Fresher to mid

    Your team's Git hosting service is down for the whole working day before a release. What can each developer still do, what is blocked, and how would the answer differ if the team used Subversion? What would you set up so that the next outage costs less?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • Version control records every saved state of a project with who, when and why, so you can compare, find and go back to any version.
  • A commit points to a tree, a snapshot of every file; unchanged files keep their blob ID and are stored once, and diffs are computed when you ask.
  • An object’s ID is a hash of its content, so the same content and the same details give the same ID on any computer.
  • Subversion keeps the only full history on a server; every Git clone holds all of it, so only push and fetch need another repository.
  • Git is the program; GitHub is one of several services that host Git repositories and add pull requests, issues and Actions.
  • Git 3.0 will change the defaults for new repositories (SHA-256, reftable, main), with no release date set.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.