给出了以下情况。
我的期望是,已经上传的文件不会再使用git push
上传。但是实际发生的情况是,当创建一个新分支时,所有文件(即使是数千个较小的源文件,而不是一个10 is文件)都会被一次又一次地上传。
我的问题是:如何让Git检测到10 My文件已经上传了?您知道如何解决/修复Git在推送提交时检测服务器上已经存在的对象吗?Git通过它的sha检测文件,因此它应该能够检测到提交树中的某些文件已经存在于服务器上。
可能的用例:我有两个完全不同的分支,但是在这两个分支中共享了一些常见的文件。当我推动一个分支,我不想再上传普通文件时,我推动第二个分支。
实际用例:我使用Python脚本和一些较小的数据集(1MB -10 1MB)做了很多机器学习实验。每次我开始一个实验时,我都会将所有必要的实验文件添加到一个新的Git树中,并在没有分支的新提交中使用该树。该提交将完全免费挂起,然后使用一个新的Git引用(例如,推荐/作业/我的-实验名称)。现在,当我对几乎相同的文件(以及两个引用)进行两次实验时,当我推送这些引用时,Git再次推送所有对象。我的带宽很低,这真的减慢了我的工作速度。
$ mkdir git-test && cd git-test
$ git init
$ git remote add origin git@gitlab.com:username/projectname.git
# create dummy 10MB file
$ head -c 10000000 /dev/urandom > dummy
$ git add dummy
$ git commit -m 'init'
# first push, uploads everything - makes sense
$ git push origin master
Counting objects: 3, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 9.54 MiB | 1.13 MiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
# create new empty branch, not based from master
$ git checkout --orphan branch2
# add same files again
$ git add dummy
$ git commit -m 'init on branch2'
# this uploads now again the dummy file (10MB), although the server
# has that object alread
$ git push origin branch3
Counting objects: 3, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 9.54 MiB | 838.00 KiB/s, done.
在技术方面,我们有:
回答(我不能再回答了,因为有人把这个标记为副本)。
不幸的是,解决办法并不那么简单。
每次Git想同步两个存储库时,它都会构建一个包文件,其中包含所有必需的对象(比如文件、提交、树)。执行git push
时,远程将所有现有引用(分支)及其头提交SHA发送到客户端。这就是问题所在:包协议不是用于每个对象,而是用于每个提交。因此,根据协议本身,上述解释的行为是正确的。为了解决这个问题,我构建了一个简单的脚本,每个脚本都可以用于基于对象执行git push
,而不是提交。
你可以在这里找到它:https://github.com/marcj/git-objects-sync
它所做的:
当然,这也有一些缺点,但我在链接的Github存储库中对它们进行了描述。
有了上面的脚本,您现在可以看到以下内容:
marc@osx ~/git-test (branch11*) $ # added new branch11 as explained at the very top
marc@osx ~/git-test (branch11*) $ python git-sync.py refs/heads/branch11
Counting objects: 1, done.
Writing objects: 100% (1/1), 158 bytes | 158.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
marc@osx ~/git-test (branch11*) $ git push origin branch11
Everything up-to-date
因此,正如您所看到的,它只同步一个对象(提交对象),而不是再次同步dummy
文件及其树对象。
发布于 2018-01-12 15:22:01
Git只使用引用的交换来开发它的清单并封装对象。如果您正在推送的分支与遥控器没有共同的祖先,它将打包并重新上传所有可从该分支访问的对象。
序列是这样的
远程将识别其数据库中已经存在的对象并使用现有对象。
逻辑是,不时发送一些不必要的文件比每次访问和比较整个历史记录(可能有数万个或数十万个对象)要高效得多。
发布于 2018-01-17 17:27:26
我认为你只需要停止使用--orphan
来创建新的实验分支。
工作流
就这样。
,怎么回事?
您坚持不使用分支,而只使用引用。然而,分支是一种参考.此外,git checkout --orphan <newthing>
是否真的创建了一个分支.问题在于,它是一个分支,它不知道以前添加到存储库中的任何内容,因为它没有父级。这与创建一个全新的存储库本质上是一样的。
如果您使用git checkout -b <newthing> master
创建新分支,那么git将不会麻烦已经在主服务器中的上传文件。
现在如何管理新的公共文件?
假设有一天你有了一个新的文件,你希望将来的所有实验都能利用它--一个新的共享/通用文件。您所需要做的就是将该文件添加到master
中,并根据更新的主分支创建您的下一个实验分支。如果希望该文件对现有/先前创建的实验可用,则只需签出这些分支并运行git pull --rebase origin master
即可。这将引入添加到master的提交,后者将包含新添加的文件。
安装复杂性
当你开始拉,事情可能会变得复杂。对于如何更新分支有几种不同的策略,使用--rebase
就是其中之一。这不是必需的,但这可能是更好的方法。还有其他需要考虑的事情,比如如何管理冲突的更改,但这些似乎超出了这个问题的范围。有大量的资源可用于解释重基/合并等。
TR;博士
不要尝试手动管理提交树和父/子关系。让git
做它的事吧。
发布于 2018-01-14 21:17:50
实际用例:我使用Python脚本和一些较小的数据集(1MB -10 1MB)做了很多机器学习实验。每次我开始实验时,我都会将所有必要的实验文件添加到一个新的Git树中。
这似乎不是一个与Git相关的问题,而是一个内容管理问题:如果您有一组公共的静态文件,您希望从一个Git回购分支重用到另一个分支,那么这组文件(它永远不会改变)一开始就不必在Git回购中。
您可以考虑将其上传到服务器中的静态路径中,并确保您的ML脚本( Git中的版本)通过从所述静态路径获取和复制初始数据集来开始其学习过程。
或者他们可能在自己的Git中,您的脚本将从克隆/更新那些数据的子文件夹开始,方法是从外部回购中克隆/提取这些数据。
这样,您就完全绕过了版本控制问题,只有版本(在您的多分支回购中专门用于您的实验)实际上可以从提交更改为提交:您的ML脚本,可能还有一些特定的(或更小的)数据集,为新的实验量身定做。
https://stackoverflow.com/questions/48228425
复制相似问题