Branches
Choose Your Own Adventure
Remember those "Choose Your Own Adventure" books? At certain points, you pick a path: "Turn to page 42 for the cave, or page 67 for the forest." Each path is a different story branching off from the same point.
Git branches work the same way. You can create a new branch to try something out, and if you don't like it, you go back to where you were. If you do like it, you merge it back into the main story.
Commits C5 and C6 only exist on the feature branch. The main
branch doesn't see them until you merge.
Heads up: merging is not yet implemented in PyGit -- it's a great exercise to try yourself! For now you can create, list, and switch branches.
What IS a Branch?
Here's the beautiful secret: a branch is just a text file that contains a commit hash. That's it!
Creating a branch = writing a new file with the current commit hash. Switching branches = updating HEAD to point to a different branch. Deleting a branch = deleting the file. The commits themselves are untouched.
HEAD: "You Are Here"
The HEAD file tells Git which branch you're currently on:
When you commit, Git updates the current branch's pointer to the new commit. HEAD doesn't change -- it still points to the branch. But the branch now points to a different commit.
Branches in PyGit
from pygit.repository import Repository
repo = Repository.init("/path/to/project")
# ... add files and commit ...
# Create a new branch.
repo.create_branch("feature")
# List all branches.
print(repo.list_branches()) # ["feature", "main"]
# Switch to the new branch.
repo.switch_branch("feature")
print(repo.current_branch()) # "feature"
Note:
switch_branchonly movesHEADto the new branch. It does not yet update the files in your working directory to match that branch (a realcheckout). Restoring files on switch is another great exercise to try yourself.
What Makes a Good Branch Name
Because a branch is a file in .pygit/refs/heads, its name has to be a
safe file name. PyGit refuses (with a RepositoryError) a name that is
empty, . or .., has a / or \ in it, has spaces or invisible
characters, or is too long for the file system. A name like
../escaped would otherwise climb out of the branches folder! PyGit
checks the name it reads back from HEAD the same way, so a hand-edited
HEAD can't send a commit somewhere else either.
Real Git is more generous: it allows names like feature/login and
keeps them in sub-folders. PyGit keeps it simpler: one branch, one
plain file name.
It also refuses a name that differs from another branch only in
capitals, like Feature next to feature, or only in how an accent is
spelled (é can be stored as one character, or as e followed by an
accent mark). On a Mac those twins would be the same file (Windows
ignores capitals too), so PyGit refuses them everywhere and behaves the
same on every computer. That rule is stricter than real Git, which
allows Feature next to feature on Linux.
What We Test
- Creating a branch stores a commit hash in a file.
- Listing branches shows all branch names.
- HEAD tracks the current branch.
- Switching branches updates HEAD.
- Unsafe names, a damaged HEAD, and names that differ only in capitals or accent spelling, are refused.
What's Next?
You've learned every concept behind Git! Blobs, trees, commits, the repository, staging, diffs, and branches. You've built a version control system from scratch -- the same tool that powers GitHub and every professional software team in the world.