Skip to content

Week 2 - M3: Real refs, HEAD, and minigit log #12

Description

@aman-a-shah

Owner:@DanisLol
Module: 3 - Commits & branching
File you own:minigit/commits.py
Week: 2 of 10 - Real Bytes on Disk

Fix first - from the Week 1 review

minigit commit -m x crashes: AttributeError: 'CommitManager' object has no attribute 'store'.
__init__ only sets self.store when store is passed. Uncomment the fallbacks:

self.store=storeorObjectStore(repo_path)
self.tree=treeorWorkingTree(repo_path)

Also raise RefNotFoundError -> raise RefNotFoundError(name) so the CLI prints something.

What changes this week

  • Week 1 refs lived in self._refs and vanished when the process exited
  • Week 2 a ref is a real file: .minigit/refs/heads/<branch>, content = one commit hash + \n
  • HEAD is a real file: ref: refs/heads/main\n

Steps

  1. Branch week2/m3-real-refs (branch off main after M1 merges)
  2. Delete self._refs and self._head. Helpers instead:
    • _ref_path(name) -> self.root / ".minigit" / "refs" / "heads" / name
    • read_head() -> str | None - ref: refs/heads/x -> "x"; raw hash -> detached, return the hash
    • write_head(name) -> write ref: refs/heads/<name>\n
    • read_ref(name) -> str | None - file missing = branch has no commits yet
    • write_ref(name, commit_hash) -> mkdir(parents=True, exist_ok=True), write hash + \n
  3. create_commit(tree_hash, parents, author, message):
    • _format_commit stays byte-for-byte identical to Week 1
    • write the commit object, then advance the current branch ref to the new hash
    • a commit that doesn't move a ref is unreachable garbage - moving the ref is the point
  4. create_branch(name, commit_hash) -> write_ref; name already exists -> MiniGitError
  5. list_branches -> sorted(p.name for p in refs_dir.iterdir()), * marks read_head()
  6. switch_branch(name) -> unknown ref = RefNotFoundError(name), else write_head(name)
    • # Week 4 - also resolve ref -> commit -> tree and call self.tree.checkout(tree_hash)
  7. minigit commit -m "<msg>" for real:
    • tree_hash = self.tree.build_tree_from_index() (still a stub hash this week - fine)
    • parents = [read_ref(current_branch)], or [] when the branch file doesn't exist yet (root commit)
    • author from .minigit/config if present, else "minigit <minigit@local>"
    • print the short hash: [main a1b2c3d] <msg>
  8. New command minigit log:
    • walk from read_ref(current) back through parents, print <hash> <message first line> per commit
    • no commits yet -> print no commits yet, return 0
    • parse the commit body back out of store.read_object(hash) - the format is yours, so is the parser
  9. merge stays return None# Week 4 fast-forward / Week 5 three-way
  10. Tests tests/test_commits.py - real ObjectStore(tmp_path), drop FakeObjectStore:
    • commit on an empty repo -> zero parent lines, ref file created
    • second commit -> one parent line, points at the first
    • the ref file actually moved
    • create_branch twice -> raises
    • switch_branch("nope") -> RefNotFoundError
    • branch, commit, switch back -> the two branches point at different hashes
    • log output has one line per commit, newest first
  11. quality-check green -> commit, push, PR

Notes

  • run minigit init (@mahis1067's, landing this week) before touching refs in a test
  • branching copies a 40-char string and zero object data - that is why it's instant

Done when

  • Week 1 store crash fixed
  • refs and HEAD are real files
  • create_commit moves the current branch ref
  • minigit commit / branch / checkout / log all work across separate CLI calls
  • tests use the real object store
  • quality-check green
  • PR open + reviewed

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

module-3Commits and branchingweek-2Week 2 - real storage and wire

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions