有些故事,我们维护了一个提交系统,该系统允许学生将源文件提交到git存储库。这样做有两种选择:对于更高级的学生,我们只是让他们使用git。对于初学者,我们有一个Web界面,允许他们将文件上传到自己的存储库。
Web界面本身是非常基本的,现在仅支持添加文件。我们还希望使学生能够删除,但是,我们需要在裸存储库上进行删除,不进行克隆。考虑到提交系统与之交互的数百个存储库,克隆操作太昂贵且需要太多空间。
我们已经能够弄清楚如何直接将文件添加到树中而不进行克隆。我们还无法找出裸露仓库中的删除部分。我尝试了以下方法。
password
从技术上讲这是可行的,它只是从存储库中删除所有文件,而这并不是我们想要的。我不确定基于git的内部原理如何从树中删除单个blob并更新裸仓库,同时保留其他文件。
有什么想法吗?
答案 0 :(得分:1)
我想我找到了一个解决方案,我不是特别喜欢它,但是它可以工作。
git log
,获取当前HEAD的sha1 ID。git read-tree --empty
,以确保我们可以添加要保留的文件,而不保留我们不保留的文件git ls-tree -r HEAD
git update-index -add --cacheinfo <value from ls-tree> <sha1 from ls-tree> <name from ls-tree>
git write-tree
保存价值echo 'removing <file>' | git commit-tree <value from previous command> -p <sha1 of current master HEAD>
保存价值git update-ref refs/heads/master <value from previous command>
如果有人碰巧知道实现此目标的更好方法,我将不知所措。我将附上一个python脚本(使用GitPython),以完成上述任务。
编辑:添加了Python(带有GitPython)
def repo_delete(repo, path: str):
"""Delete the specified file at <path> from the repository."""
headSha = repo.heads[0].commit.hexsha
import re
g = repo.git
tree = g.ls_tree("-r", "HEAD")
g.read_tree("--empty")
for blob in tree.split("\n"):
blob_parts = re.split("[ \t]", blob)
if blob_parts[3] != path:
print(f"adding {blob_parts[3]}")
g.update_index("--add", "--cacheinfo", blob_parts[0], blob_parts[2], blob_parts[3])
treeSha = g.write_tree()
newHeadSha = g.commit_tree(treeSha, "-m", f'"removing {path}"', "-p", headSha)
g.update_ref("refs/heads/master", newHeadSha)
print("done")