【问题标题】:pushing limited commit history to remote git将有限的提交历史推送到远程 git
【发布时间】:2017-04-11 14:58:54
【问题描述】:

我在学校的实验室机器上有一个 git 存储库,并且遇到了我一直试图解决的问题。

由于我们使用的 CUDA SDK 的安排,我在同一个目录中有两个遥控器,但我不希望来自一个遥控器的所有提交,原点,被推送到另一个遥控器,“proj1”。下面我会更清楚:

最初,该目录有一个带有单个远程的 git 存储库,例如,以下提交历史记录:

A-B-C-D-E <-(origin/master)

然后我添加了第二个远程并创建了一个本地分支,我将从该分支推送和获取:

A-B-C-D-E-G <-(origin/master) (master)
        '        
        '-F-H-I <-(proj1/newbranch) (newbranch)

现在,当我将我的更改从“newbranch”推送到远程“proj1/newbranch”时,我不想用它推送 A-E 提交,我只想从 F 推送。

我知道一个孤立的分支正是我在这里寻找的,但是我们的实验室正在运行 git 1.7.x,它还没有该功能,并且让管理员更新它需要很长时间(我们当然没有权限自己做)。

我还读到我可以使用 rebase 重新排序我的提交,以便 F 是最旧的提交,然后我可以将单个提交推送到“proj1”。但是这样做不会改变/弄乱我在主分支上的历史吗? (A-E 已经在 origin/master 上)

所以我想知道我是否缺少 git 的某些功能来完成我想要的?是否有其他方法可以删除“newbranch”的提交历史或至少将其中断?也许我正在做的是不好的做法,但就像我说的,我需要在这个目录中拥有 CUDA SDK 的所有文件,我不想弄乱它。

【问题讨论】:

  • 我不确定我是否理解您的问题。如果您的远程和本地分支的当前状态与上图相同,并且您向本地“newbranch”添加了一些提交,例如-J-K-L,那么当您将 newbranch 推送到 proj1/newbranch 时,显然只会推送“-JKL”,无需重新推送“AE”。
  • 我可能对此不清楚。到目前为止,我的本地“新分支”只有提交 F(我尝试推送,但它当然推送了 while 历史,所以我取消了它)。所以 F 还没有推送到“proj1”。
  • 当你说你本地的新分支只有commit F,你的意思是说当你运行“git log newbranch”时你在历史中只看到一个commit F,和它无关“起源/主人”?如果是这样,您本地的新分支已经是一个孤立的分支,将其推送到孤立的远程是微不足道的,所以您必须描述其他情况。
  • 不,我创建了本地分支(git branch newbranch),签出新分支(git checkout newbranch)。然后我跑了“git fetch proj1/newbranch”(newbranch 在远程),最后我跑了 git merge proj1/newbranch。然后做了一个提交,F。当我运行 git log 时,我看到 A - F,正如我提到的,我们实验室中的 git 版本没有孤儿
  • 每个 Git 都支持孤立分支;他们刚刚在 1.7.x 中获得了一个漂亮的界面。无论如何,这对你一点帮助都没有。无论你想要什么,它都不是孤立的分支。

标签: git github push git-commit git-fetch


【解决方案1】:

[[tl;dr...如果您可以将“origin”项目作为“proj1”项目的子目录并使用Gi​​t子模块,您将过上幸福安宁的生活。如果你不能或不愿意,你注定要花 10% 的时间在“proj1”开发上,90% 的时间与 Git 血战。]]

好的,我几乎可以肯定,你认为你需要的方式来解决这个问题不仅是不好的做法,而且是行不通的,所以作为一名 Git 用户,我有道德责任告诉你你应该做什么,而不是帮助你做你认为你应该做的事。也许其他人会提出一个我没有想到的神奇解决方案,但我不会屏住呼吸。

我认为您需要接受这样一个事实,即这是两个独立的项目,并且它们需要有两个独立的工作目录(带有单独的“.git”子目录)。当然,这带来了两个直接的问题。首先,如果您需要将这些文件大量混合在同一个目录中,这似乎不可行;我尝试在下面解决这个问题。其次,如果目录是完全独立的,那么它们的历史将被完全独立地跟踪,因此当您提交特定版本的“proj1”时,您将不会记录使用哪个版本的“origin”来运行它。

如果您确实想要跟踪“proj1”的每次提交所使用的“origin”版本,那么 Git 子模块(请参阅 git help submodule)是不错的选择。为此,“origin”必须保存在“proj1”树的自己的子目录中。您可以随意组织“proj1”的其余部分。同样,如果您需要混合文件,请参见下文。当开发在一个项目(“proj1”)上进行并且第二个项目(“origin”)只是为了方便保持最新并记住哪个版本的“origin”而使用 Git 时,Git 子模块运行良好用于运行哪个版本的“proj1”。 (如果需要,子模块允许对第二个项目进行更改,但是让一切正常工作有点麻烦,所以如果子模块只是“只读”会更好。)

顺便说一句,Git 子树(不是孤立的分支)是最接近于做你认为你想做的事情的事情,但是它们确实需要将“子”项目放在它的自己的专用子目录,它们确实要求子项目的整个历史都包含在主项目中;他们只是允许子项目被拆分并独立推或拉。理论上,您可以将它们用于您的设置,将“origin”视为主项目,并将“proj1”作为“子树”保存在单独的子目录中。您将像往常一样在存储库上工作,“git subtree”将提供一种机制来分离“proj1”子树中正在完成的工作并单独提交。太好了,对吧?可悲的是,子树只能作为 Git 1.7.10 及更高版本的贡献模块(默认情况下未安装,我不认为)。但是,你可以尝试“git help subtree”来检查。

但是,任何这些解决方案都需要将一个项目隔离在其自己的子目录中。

如果文件绝对必须混合在一个目录中,那么您将陷入痛苦的世界:最直接的方法是仍然维护两个单独的 Git 工作目录(或 Git 子树)使用上述机制(即,完全独立或使用子模块或子树的另一个子目录),然后构建符号链接树。符号链接树可以:

  1. 成为您实际运行项目的单独“构建”目录,所有文件的符号链接都指向每个真正的“proj1”和“origin”工作目录。

  2. 是一组实际添加到“proj1”工作目录并签入到存储库的符号链接。它们都可以指向作为子模块管理的子目录中的“origin”副本。

我能想到的符号链接树的唯一替代方法是更多痛苦。从技术上讲,您可以设置一个“.gitignore”所有“原始”文件的“proj1”工作目录。然后,您可以愉快地运行“git”来仅管理“proj1”文件,而忽略任何“来源”内容。当您想使用“origin”(例如,使用“git pull”更新它)时,您可以使用“--git-dir”和/或“--work-tree”参数运行 Git 以匹配您的具有不同“.git”目录的工作树(配置为使用备用“.gitignore-origin”文件或其他东西)。我从来没有尝试过,这听起来很可怕,但你可能会让它发挥作用。

现在,至于 Git 存储库的当前状态,您遇到了问题。您的“新分支”现在与“起源”项目的历史深深交织在一起,没有简单的方法可以将其分开。如果你想重建历史,你要么需要使用一些过滤器分支黑魔法,要么你需要手动完成(例如,对于从头到尾的每个提交,在你当前的树中检查它,复制“proj1 " 文件复制到一个新的 Git 工作目录,忽略任何“原始”文件,然后重新提交)。

关于孤儿分支,他们不会在这里帮助你。孤立分支只是普通的旧分支,恰好与同一存储库中的其他分支不共享任何历史记录。它可能看起来像你所追求的,但是一旦你经历了设置它们的痛苦,你会发现一些令人痛苦的事情。当您“git checkout newproj”在“proj1”上工作时,Git 将检查您所有的“newproj”文件并删除所有 CUDA API 文件!当您“git checkout master”访问 CUDA API 文件时,Git 将检查它们并删除所有“newproj”文件!如何一次获取所有文件?显然,您设置了两个独立的工作目录并在一个中检查“newproj”并在另一个中检查“master”,然后使用上述方法之一将它们组合起来。与将这些视为完全独立的项目相比,它没有任何优势。你不能有一个孤立的分支,以某种方式“保留”CUDA API 文件而不让它们签入分支。

【讨论】:

  • 很好的答案 - 但可能需要在顶部添加 TL;DR
  • 好建议 - 我加了一个。
  • 不错的总结。这样做或受苦:) 我同意子模块将是更好的解决方案。子树太难管理且不受工具支持。
  • 感谢您的回答,看来使用两个单独的工作目录将是迄今为止最轻松、最正确的方法。
  • 我没有首先这样做的唯一原因是我不确定 CUDA SDK 中的构建过程和常见的 makefile 是否需要调整。但是在阅读了您的答案之后,我认为这比继续我的解决方案要少得多。作为 git 的相对新手,我相信当我读到孤儿分支功能时,我得到了隧道视野,我认为我试图做的事情在 git 中并不少见(听起来它正是为此目的而制作的)。因此,在托管在两个单独的遥控器上的同一工作目录中维护两个独立的项目是不好的。
猜你喜欢
  • 2021-06-24
  • 2013-04-08
  • 2013-11-25
  • 2017-10-17
  • 2013-12-06
  • 1970-01-01
  • 2014-05-05
  • 2019-01-16
  • 2014-01-25
相关资源
最近更新 更多