将旧版本(不受版本控制)添加到 git 存储库作为标记提交
Add an old version (out of version control) to the git repository as a tagged commit
我有一个系统 sys/master
的 git 存储库,它是我在系统创建一段时间后创建的。我有一个系统备份 sys_bk
是在创建存储库之前完成的。
在不影响系统最新版本的情况下,将sys_bk
版本作为标记版本添加到当前存储库的推荐方法是什么?
仅供参考,sys_bk
和 sys/master
之间的差异很大。
我想到的最简单的方法是利用 git 的 git checkout --orphan <branch>
命令,这样您就可以创建一个没有父级的分支以及 sys_bk
文件夹的内容作为初始提交。
示例工作流程:
git checkout --orphan sys_bk
(签出一个没有父节点的新分支)
git rm -rf .
(从工作目录中删除所有文件)
cp /path/to/sys_bk/* ./
(移动 sys_bk
个文件到工作目录)
git add --all .
(将所有新 sys_bk
文件添加到索引)
git commit -m "Add sys_bk"
我认为这里真正没有答案的问题是,您希望这个新(/旧)提交如何出现在历史记录中?今天你的历史开始于晚些时候
D -- E -- F <--(master)
现在你有一些旧版本 A
。一些用户(jof 在他的回答中,StephenNewell 和 torek 在评论中)提到了将 A
添加到您的 repo 的方法。这会让你得到类似
的东西
D -- E -- F <--(master)
A <--(sys_bk)
然后 StephenNewell 建议合并不相关的历史记录,但我真的怀疑那是你想要做的。您指定不更改项目的当前版本,因此充其量它是一种特殊类型的邪恶合并。基本上你最终会得到
D -- E -- F -- M <--(master)
/
A <--(sys_bk)
但 M
处的内容 (TREE
) 不会是该历史记录的 default/expected 合并结果;相反,它将是 F
处的 TREE
的副本。因此,合并可能会导致麻烦,而且它并没有很好地反映 A
在项目历史中的真实位置。
一个选择是让历史不相关。您可以保留用于将 A
带入回购的 sys_bk
分支,and/or 您可以标记 A
(这听起来像您打算做的),并且它会被保存下来,供任何愿意寻找它的人使用。 (好吧,如果您保留分支而不仅仅是一个标签,可见性可能是最简单的;这取决于您如何记录您正在做的事情。)
另一件需要考虑的合理事情是使 A
看起来像 D
的 parent。有几种方法可以解决这个问题,各有利弊。
改写历史
重写历史以物理连接 A
作为 D
的 parent(大致)是您支付成本 up-front 的选项,然后一切从此工作顺利。但是取决于有多少人分享你的 repo,up-front 成本可能会相当大,并且每个人都支付它,无论他们是否关心 A
。
如果您想使用此选项,请参阅 git filter-branch
和 --parent-filter
选项的文档。最后你会得到类似
的东西
A -- d -- e -- f <--(master)
我正在使用 d
来识别 TREE
与 D
完全相同的新提交。 (关于它的一切都像 D
,除了它有一个 parent - A
- 而 D
没有 parent。)这与典型的略有不同"rewritten commit" 来自 rebase - 特别是在 d
的情况下 - 这就是为什么我使用 lower-case 而不是素数表示法。但结果是一样的:这些都是新的提交。
这意味着,假设 master
(and/or 任何其他参考)已经被推送到远程,您将必须 "force push" - git push -f
- 用新的引用覆盖那些引用,或者只是丢弃遥控器并在其位置放置一个新的。无论哪种方式,每个其他用户都将处于损坏状态,他们必须小心纠正以避免撤消您所做的事情(请参阅 git rebase
文档中的 "Recovering from Upstream Rebase")。
Object替换
一种侵入性较小的方法是更新单个存储库 "as needed",使它们的行为就好像 A
是 D
的 parent。在这种情况下,任何不关心将 A
视为 D
的 parent 的人都完全不受影响。不利的一面是 (a) 它需要在每个需要它的 repo 上进行设置,并且 (b) 它有一些已知的 bugs/quirks - 请参阅 git replace
文档。
为方便起见,您需要复制一份提交 D
。您以类似于历史重写的方式执行此操作,除了您创建一个新分支来重写并保留所有其他分支。
所以你会计算出一个引用 D
的表达式。 (也许你得到它的提交 ID,或者在我们的例子中我们可以使用 master~2
。)
git checkout master~2
git checkout -b sys_bk_replacement
然后 运行 git filter-branch
与完全重写的方式大致相同,但仅指定 sys_bk_replacement
分支(不是 --all
因为你可能会完全重写)。这会给你
D -- E -- F <--(master)
A <--(sys_bk)
\
d <--(sys_bk_replacement)
并且任何想要 A
看起来像 D
的 parent 的人都可以使用 git replace
将 d
替换为 D
。
我有一个系统 sys/master
的 git 存储库,它是我在系统创建一段时间后创建的。我有一个系统备份 sys_bk
是在创建存储库之前完成的。
在不影响系统最新版本的情况下,将sys_bk
版本作为标记版本添加到当前存储库的推荐方法是什么?
仅供参考,sys_bk
和 sys/master
之间的差异很大。
我想到的最简单的方法是利用 git 的 git checkout --orphan <branch>
命令,这样您就可以创建一个没有父级的分支以及 sys_bk
文件夹的内容作为初始提交。
示例工作流程:
git checkout --orphan sys_bk
(签出一个没有父节点的新分支)git rm -rf .
(从工作目录中删除所有文件)cp /path/to/sys_bk/* ./
(移动sys_bk
个文件到工作目录)git add --all .
(将所有新sys_bk
文件添加到索引)git commit -m "Add sys_bk"
我认为这里真正没有答案的问题是,您希望这个新(/旧)提交如何出现在历史记录中?今天你的历史开始于晚些时候
D -- E -- F <--(master)
现在你有一些旧版本 A
。一些用户(jof 在他的回答中,StephenNewell 和 torek 在评论中)提到了将 A
添加到您的 repo 的方法。这会让你得到类似
D -- E -- F <--(master)
A <--(sys_bk)
然后 StephenNewell 建议合并不相关的历史记录,但我真的怀疑那是你想要做的。您指定不更改项目的当前版本,因此充其量它是一种特殊类型的邪恶合并。基本上你最终会得到
D -- E -- F -- M <--(master)
/
A <--(sys_bk)
但 M
处的内容 (TREE
) 不会是该历史记录的 default/expected 合并结果;相反,它将是 F
处的 TREE
的副本。因此,合并可能会导致麻烦,而且它并没有很好地反映 A
在项目历史中的真实位置。
一个选择是让历史不相关。您可以保留用于将 A
带入回购的 sys_bk
分支,and/or 您可以标记 A
(这听起来像您打算做的),并且它会被保存下来,供任何愿意寻找它的人使用。 (好吧,如果您保留分支而不仅仅是一个标签,可见性可能是最简单的;这取决于您如何记录您正在做的事情。)
另一件需要考虑的合理事情是使 A
看起来像 D
的 parent。有几种方法可以解决这个问题,各有利弊。
改写历史
重写历史以物理连接 A
作为 D
的 parent(大致)是您支付成本 up-front 的选项,然后一切从此工作顺利。但是取决于有多少人分享你的 repo,up-front 成本可能会相当大,并且每个人都支付它,无论他们是否关心 A
。
如果您想使用此选项,请参阅 git filter-branch
和 --parent-filter
选项的文档。最后你会得到类似
A -- d -- e -- f <--(master)
我正在使用 d
来识别 TREE
与 D
完全相同的新提交。 (关于它的一切都像 D
,除了它有一个 parent - A
- 而 D
没有 parent。)这与典型的略有不同"rewritten commit" 来自 rebase - 特别是在 d
的情况下 - 这就是为什么我使用 lower-case 而不是素数表示法。但结果是一样的:这些都是新的提交。
这意味着,假设 master
(and/or 任何其他参考)已经被推送到远程,您将必须 "force push" - git push -f
- 用新的引用覆盖那些引用,或者只是丢弃遥控器并在其位置放置一个新的。无论哪种方式,每个其他用户都将处于损坏状态,他们必须小心纠正以避免撤消您所做的事情(请参阅 git rebase
文档中的 "Recovering from Upstream Rebase")。
Object替换
一种侵入性较小的方法是更新单个存储库 "as needed",使它们的行为就好像 A
是 D
的 parent。在这种情况下,任何不关心将 A
视为 D
的 parent 的人都完全不受影响。不利的一面是 (a) 它需要在每个需要它的 repo 上进行设置,并且 (b) 它有一些已知的 bugs/quirks - 请参阅 git replace
文档。
为方便起见,您需要复制一份提交 D
。您以类似于历史重写的方式执行此操作,除了您创建一个新分支来重写并保留所有其他分支。
所以你会计算出一个引用 D
的表达式。 (也许你得到它的提交 ID,或者在我们的例子中我们可以使用 master~2
。)
git checkout master~2
git checkout -b sys_bk_replacement
然后 运行 git filter-branch
与完全重写的方式大致相同,但仅指定 sys_bk_replacement
分支(不是 --all
因为你可能会完全重写)。这会给你
D -- E -- F <--(master)
A <--(sys_bk)
\
d <--(sys_bk_replacement)
并且任何想要 A
看起来像 D
的 parent 的人都可以使用 git replace
将 d
替换为 D
。