{"id":22974965,"url":"https://github.com/ignorantshr/mgit","last_synced_at":"2025-04-02T07:41:48.597Z","repository":{"id":215066347,"uuid":"738034407","full_name":"ignorantshr/mgit","owner":"ignorantshr","description":"Write yourself a Git!","archived":false,"fork":false,"pushed_at":"2024-01-02T09:19:03.000Z","size":53,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-07T22:34:52.154Z","etag":null,"topics":["git","go","golang-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ignorantshr.png","metadata":{"files":{"readme":"README_ZH.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2024-01-02T09:01:41.000Z","updated_at":"2024-12-09T06:52:02.000Z","dependencies_parsed_at":"2024-01-02T10:28:18.280Z","dependency_job_id":"c2a293d8-04c0-4952-bc7b-8bf47d3a01bf","html_url":"https://github.com/ignorantshr/mgit","commit_stats":null,"previous_names":["ignorantshr/mgit"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignorantshr%2Fmgit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignorantshr%2Fmgit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignorantshr%2Fmgit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ignorantshr%2Fmgit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ignorantshr","download_url":"https://codeload.github.com/ignorantshr/mgit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246777829,"owners_count":20832032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","go","golang-tools"],"created_at":"2024-12-15T00:21:03.463Z","updated_at":"2025-04-02T07:41:48.567Z","avatar_url":"https://github.com/ignorantshr.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# MGit\n从零实现一个 git，参考来源：[Write yourself a Git!](https://wyag.thb.lt/)。\n为了与 `.git` 区分，本工具使用 `.mgit` 作为版本控制系统的目录。\n\n看源码之前建议先了解一下下面的相关概念。\n\n## 概念：\n\n### 对象\n- `object`。git 用来管理、组织、存储、的形式。例如 blob、tree、commit、tag 都是 object。\n\n    object 通过 hash 算法生成一个 hash 值作为文件名，文件内容存放各种 object 的具体内容，存放在 `.git/objects` 目录下面。\n\n- `blob`。存储仓库中的单个文件内容。\n- `tree`。描述仓库的内容。tree 将 blob 和 子树 关联起来，组织成一棵树，形成树状结构，这样就为恢复历史版本提供了依据。`git checkout` 其实就是找到树，然后根据其描述的组织关系恢复到系统文件。\n\n### 引用\n- 引用机制。除了通过 object 存储对象，git 还采取了引用机制来方便组织和管理它们。引用分为 直接引用 和 间接引用 两种形式：\n    - `.git/refs` 下存放的是直接引用，也就是说他们的文件内容直接指向某个 object\n    - `.git/HEAD` 在一般情况下存放的是间接引用形式，例如`ref: refs/heads/master`，可以通过指向的文件路径寻找其存放的 object hash 值，从而找到具体文件。\n- `tag`。tag 可以理解为指向任何对象的引用。分为轻量级 tag 和带信息的 tag，后者就是 tag object。存放在`refs/tags`目录。\n- `branch`。branch 其实就是指向某个 commit 的引用。存放在`refs/heads`目录。\n- `HEAD`。HEAD 是指向当前 branch 或 某个 commit 的引用，用于跟随定位你在哪个历史版本的位置。\n\n### 索引文件\n\n- `index file` 或 `staging area`。要在 Git 中提交，首先需要使用 `git add` 和 `git rm` “暂存” 一些更改，然后才能提交这些更改。在最后一次提交和下一次提交之间的这个中间阶段称为“暂存区域”。\n\n    git 使用 `index file` 来实现暂存区的管理。index 文件记录了文件的信息，通过与 HEAD 指向的 tree 作对比，可以得出暂存区与 HEAD 的差异；通过与 文件系统（仓库中的实际文件） 作对比，可以得出暂存区与 文件系统 的差异；通过这两次对比就能实现`git status`命令，知道 修改了什么文件、新增了什么文件、删除了什么文件。\n    `git add/rm` 命令用来修改索引文件内容；然后需要 `git commit` 来把索引文件保存到磁盘上成为一个历史版本。\n- `commit`。commit 命令主要就是把 index 里面平铺的结构按照树形结构写回磁盘，将 commit 和 tree 关联起来，附加一些提交信息，即构成了一次提交对象。将 commit 对象写到磁盘之后，还会更新分支所指向的 commit。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fignorantshr%2Fmgit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fignorantshr%2Fmgit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fignorantshr%2Fmgit/lists"}