git 结帐是如何实现的?

How is git checkout implemented?

当运行git checkout时,旧的HEAD和新的HEAD的mergebase可以任意往前。天真的实现是线性应用每个差异,但操作立即运行。

我有一种预感,它可能会通过某种用于中间差异缓存的跳过列表来实现,但这只是一个猜测。

有人知道它是如何实现的吗?谢谢! :)

Mary Rose Cook.

javascript implementation of Git (as an exercise) Gitlet 中如何(原则上)实施结帐,这是一个很好的例子

annotated source code

对于结帐,步骤是:

  • checkout() changes the index, working copy and HEAD to reflect the content of ref.
    ref might be a branch name or a commit hash.
  • Get the hash of the commit to check out.
  • Abort if ref cannot be found.
  • Abort if the hash to check out points to an object that is a not a commit.
  • Abort if ref is the name of the branch currently checked out. Abort if head is detached, ref is a commit hash and HEAD is pointing at that hash.
  • Get a list of files changed in the working copy.
    Get a list of the files that are different in the head commit and the commit to check out.
    If any files appear in both lists then abort.
  • Otherwise, perform the checkout.
  • If the ref is in the objects directory, it must be a hash and so this checkout is detaching the head.
  • Get the list of differences between the current commit and the commit to check out. Write them to the working copy.
  • Write the commit being checked out to HEAD.
    If the head is being detached, the commit hash is written directly to the HEAD file.
    If the head is not being detached, the branch being checked out is written to HEAD.
  • Set the index to the contents of the commit being checked out.
  • Report the result of the checkout.

同样,这是一种简化(与实际的 Git 代码相比),但它很好地说明了结帐应该如何工作。

有关更多信息,您可以收听 Thomas Ferris Nicolaisen 的 GitMinutes #31: Mary Rose Cook on Gitlet 播客节目。