首页 > 解决方案 > 是否可以控制 git 存储库状态的版本?

问题描述

我正在编写一个交互式 git 教程,用户通过遵循一系列说明并操作真实的 git 存储库来学习如何使用 git。为了防止学习者破坏存储库或采取错误步骤(导致教程无法继续),我正在考虑每隔几个步骤拍摄存储库状态的快照(参考、索引和 HEAD 等)并重置当意外发生时,到最后一个。

由于拍摄回购快照对我来说听起来像是对文件夹进行某种版本控制.git,我想知道是否可以使用任何版本控制工具来完成这项工作?

我试图将一个 git repo 放在另一个 git repo 中,并将父 repo 的 .gitignore 设置为包含孩子的 .git 文件夹,但没有运气。git status不显示.git为未跟踪的目录。

很高兴听到任何可以帮助我拍摄.git文件夹快照的想法或技巧以保留 git repo 的状态并稍后应用它。

编辑 1

试图git add -f强制添加.git文件夹,但 git 拒绝添加并抛出错误消息。

幸运的是,另一个非常愚蠢的技巧奏效了。重命名.git为任何其他名称足以欺骗 git 将其视为普通文件夹。这对我来说是一个可以接受的解决方案,但并不完美。

话虽这么说,由于@ErikMD 提到我试图通过复制来保存 git 存储库状态.git乍一看似乎并不可行,我想知道我是否忽略了一些关键的东西?.git通过版本控制收费来管理 git 存储库的快照会有什么问题吗?

标签: git

解决方案


乍一看,您的“解决方法”似乎不可行(如果您尝试提交.git包含在父 git repo 中的子文件夹,您将得到某种(损坏的)git-submodule ...)

更准确地说: Git 并非旨在将文件夹的低级内容.git作为常规文件进行跟踪。相反,Git 允许.git在根存储库中组合多个存储库(多个子文件夹包含自己的子文件夹)。这对应于所谓的git 子模块功能。但是正确设置子模块需要使用专用命令,这反过来也会更新特殊文件.gitmodules。因此,我之前说过,如果您不遵循正常的工作流程,您可能会获得“损坏的 git-submodule 布局”。实际上,与git subtree等更新的功能相比,在实践中使用 git-submodules 相当繁琐。

但是我认为您可以通过依靠git reflog或相关命令来恢复=覆盖历史记录、索引和工作目录(存储库的 3 个主要部分)来实现您想要的(促进自动教程系统的 repo 恢复) ) 以及分支和标签……</p>

举例说明我的建议,假设我们只处理一个分支:

  1. 当前活动分支 ( HEAD) 的“状态”可以通过相应的 SHA1 来识别:

    $ git rev-parse --verify HEAD
    0ed45a5994bceea7c6b1d6530c72cd9ce29a46af  # for example
    
  2. 假设用户做了一个错误的步骤:

    $ git add UnwantedFile && git commit -m "Unwanted commit"
      # or
    $ git reset --hard HEAD~3  # remove 3 commits by mistake
    

    (并且您会使用适当的命令注意到它)

  3. 然后您可以恢复工作目录的状态。+ 索引 + 当前分支通过执行:

    $ git reset --hard 0ed45a5994bceea7c6b1d6530c72cd9ce29a46af
    

    (或者如果一开始没有执行第 1 步来记住之前的状态,那么 reflog 可以给出所需的提示):

    $ git reflog
    d62277c84 HEAD@{0}: reset: moving to HEAD~3
    0ed45a599 HEAD@{1}: checkout: moving from master to V8.8.2
    …
    $ git reset --hard HEAD@{1}
    

总而言之,我只看到三种方法来实现你想要的:

  1. 如果您想回滚它,请使用手动rsyncbashhacks 覆盖 repo,但这可能不太令人满意;
  2. 使用标准命令,例如git reset、或...(取决于您正在处理的教程的重点)相应地重置 repo;git branchgit checkoutgit tag
  3. 或者使用带有适当命令的本地远程(或本地克隆,以一种或另一种方式),例如git push --mirroror git pull/ git fetch?

推荐阅读