题 做一个“混帐出口”(如“SVN出口”)?


我一直想知道是否有一个好的“git export”解决方案可以创建一个没有的树的副本 .git 存储库目录。我知道至少有三种方法:

  1. git clone 然后删除 .git 存储库目录。
  2. git checkout-index 提到这个功能,但开头是“只需将所需的树读入索引...”,我不完全确定如何做。
  3. git-export 是第三方脚本,基本上是一个 git clone 进入临时位置 rsync --exclude='.git' 进入最终目的地。

这些解决方案都没有让我感到满意。最接近的一个 svn export 可能是选项1,因为这两个要求的目标目录是空的第一个。但是选项2似乎更胜一筹,假设我能弄清楚这是什么意思读一棵树到索引。


2165
2017-10-02 02:21


起源


@rnrTom:见Somov的回答。 (在tar档案中没有“压缩”)。 - etarion
@mrTom git archive --format zip --output "output.zip" master -0 将为您提供未压缩的存档(-0是未压缩的标志)。 git-scm.com/docs/git-archive。
我同意@mrTom,我不认为存档是压缩还是未压缩是主要问题。有了SVN,我可以 export 直接来自远程存储库的250 kB子目录(否则可能是200 MB大小,不包括修订版) - 我只会在250 kB(左右)下载传输中点击网络。同 git, archive 必须在服务器上启用(所以我不能尝试) - clone --depth 1 从服务器可能仍然检索说25 MB的回购,其中 .git 子文件夹单独需要15MB。因此,我仍然说答案是“不”。 - sdaau
@mrTom答案其实就是这样 是 请参阅OP的答案 - 命令是 git checkout-index - nocache
这是一个很简单的方法: git archive -o latest.zip HEAD - Evgeni Sergeev


答案:


实现这一目标的最简单方法可能就是 git archive。如果你真的需要扩展树,你可以做这样的事情。

git archive master | tar -x -C /somewhere/else

大多数时候我需要从git“导出”某些东西,我想要一个压缩存档,所以我做这样的事情。

git archive master | bzip2 >source-tree.tar.bz2

ZIP存档:

git archive --format zip --output /full/path/to/zipfile.zip master 

git help archive 有关详细信息,它非常灵活。


请注意,即使存档不包含.git目录,它也会包含其他隐藏的git特定文件,如.gitignore,.gitattributes等。如果您不想在存档中使用它们,请确保使用.gitattributes文件中的export-ignore属性,并在进行归档之前提交此属性。 阅读更多...


注意:如果您对导出索引感兴趣,则命令为

git checkout-index -a -f --prefix=/destination/path/

(看到 格雷格的回答 更多细节)


2198
2017-10-02 18:13



ZIP存档: git archive --format zip --output /full/path master - Stream
请注意,存档不包含.git目录,但会包含其他隐藏的git特定文件,如.gitignore,.gitattributes等。因此,如果您不需要它们,请确保使用export-ignore属性一个.gitattributes文件并在进行归档之前提交它。看到 feeding.cloud.geek.nz/2010/02/... - mj1531
要跟进Streams的注意事项:您可以在命令中添加'--prefix = something /'字符串来控制将在zip中打包的目录名称。例如,如果您使用 git archive --format zip --output /path/to/file.zip --prefix=newdir/ master 输出将被称为'file.zip'但是当你解压缩它时,顶级目录将是'newdir'。 (如果省略--prefix属性,则顶级目录将为'file'。) - Alan W. Smith
最简单的方法: git archive -o latest.zip HEAD 它创建一个Zip存档,其中包含当前分支上最新提交的内容。请注意,输出格式是由输出文件的扩展名推断的。 - nacho4d
它不支持git子模块:( - umpirsky


我发现了2选项意味着什么。从存储库中,您可以执行以下操作:

git checkout-index -a -f --prefix=/destination/path/

路径末尾的斜杠很重要,否则会导致文件位于/ destination中,前缀为“path”。

由于在正常情况下索引包含存储库的内容,因此“将所需的树读入索引”没有什么特别之处。它已经存在了。

-a flag需要检查索引中的所有文件(我不确定在这种情况下省略此标志意味着什么,因为它不能做我想要的)。该 -f 标志强制覆盖输出,此命令不通常做任何现有的文件。

这似乎是一种“混帐出口”我一直在寻找的。


301
2017-10-02 03:03



...并且不要忘记结束时的滑动,否则你将无法达到预期的效果;) - conny
该 git add 命令改变了索引中的内容,所以无论如何 git status 显示为“待承诺”是 分歧 HEAD和索引的内容之间。 - Greg Hewgill
@conny:阅读你的评论,忘了它并运行命令而没有斜杠。提示:按照conny的建议 - .- - Znarkus
+1给conny的建议。另外,不要尝试创建'〜/ dest /',因为这会在您的工作目录中创建一个名为'〜'的目录,而不是您真正想要的目录。猜猜当你盲目地输入rm -rf~时会发生什么 - Kyle Heironimus
@KyleHeironimus - 如果您在前缀路径周围使用引号告诉shell不执行波浪扩展,那么关于使用'〜/ dest /`的警告是真的。一个叫做的目录 ~ (不 '~' !)将在你的工作目录中创建。没什么特别的 git checkout-index 在这方面:同样如此 mkdir '~/dest' (不要那样做!)。避免需要引用的文件名的另一个好理由(例如,其中有空格):-) - Matt Wallis


git archive 也适用于远程存储库。

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master | tar -xf -

要在repo中导出特定路径,请添加尽可能多的路径作为git的最后一个参数,例如:

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv

241
2017-12-09 18:59



这个是我最喜欢的选项。它还有一个额外的好处,它也适用于裸存储库。 - innaM
改进的版本是: git archive --format=tar --prefix=PROJECT_NAME/ --remote=USER@SERVER:PROJECT_NAME.git master | tar -xf -  (确保您的存档位于文件夹中) - Nick
注意:服务器必须启用此功能。 - Jakub Narębski
我试过了 : git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git master 并致命:协议不支持操作。意外的命令流结束。 - andyf
@andyf GitHub有自己的方式: curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf - 每 文档 - bishop


enter image description here

如果存储库托管在GitHub上,则应回答特殊情况。

只是用 svn export

据我所知,Github不允许 archive --remote。虽然GitHub是 svn兼容 他们确实有所有的git回购 svn 可访问,所以你可以使用 svn export 就像你通常会与您的GitHub网址一些调整。

例如,要导出整个存储库,请注意如何 trunk在URL替换 master (或者不管怎样 project的HEAD分支设置为):

svn export https://github.com/username/repo-name/trunk/

您可以导出单个文件甚至某个路径或文件夹:

svn export https://github.com/username/repo-name/trunk/src/lib/folder

示例 jQuery JavaScript库

HEAD 分支或  分支将可用 trunk

svn ls https://github.com/jquery/jquery/trunk

HEAD  分支机构 将在下面访问 /branches/

svn ls https://github.com/jquery/jquery/branches/2.1-stable

所有 标签 下 /tags/ 以同样的方式:

svn ls https://github.com/jquery/jquery/tags/2.1.3

48
2017-10-30 17:03



git archive 只要您使用git协议,只需替换即可与GitHub一起使用 https:// 同 git:// 在URL中。我不知道为什么GitHub不宣传这个隐藏的功能。 - Neil Mayhew
@NeilMayhew这对我不起作用,我明白了 fatal: The remote end hung up unexpectedly。用jQuery github repo在两个不同的服务器上试用。 - Anthony Hatzopoulos
你是对的。我忘了我在用 git config url.<base>.insteadOf 缓存远程存储库。因此我使用了 file:// 现实中的URL。我不信 git archive 可以合作 git:// URL,因为它需要能够运行 git-upload-archive 在远端。应该可以使用 ssh 协议,除了github不允许它(Invalid command: 'git-upload-archive')。 - Neil Mayhew
如果我想在内部托管的git存储库上执行它,任何使用本地服务器工具的方式都像github一样? - kriss
upvoted - Git没有这个功能是完全奇怪的,我们不得不求助于svn - Jason S


来自 Git手册

使用git-checkout-index“导出整个树”

前缀能力基本上使得git-checkout-index用作“export as tree”函数变得微不足道。只需将所需的树读入索引,然后执行:

$ git checkout-index --prefix=git-export-dir/ -a


38
2017-10-02 02:27



我认为混淆是“将所需的树读入索引”这一短语。 - davetron5000
如果要在分支栏中导出目录foo,那么这将是 git read-tree bar:foo 接着 git checkout-index --prefix=export_dir/ -a 之后也许你应该这样做 git update-index master - Pascal Rosin
我不知道为什么这不是公认的答案。 - John Weldon
@JohnWeldon你是否需要先克隆回购?如果是这样,那么我就不接受它,因为子目录的“svn export”的全部意义是直接获取该子目录的副本;如果有人拥有1GB的Git仓库并且我想要的只是一个10kB的子目录,那么要求我克隆整个东西是疯狂的。 - Jason S
我也回复@ davetron5000,注释“将所需的树读入索引”,我不知道这意味着什么。 - Jason S


我写了一个简单的包装器 git-checkout-index 你可以像这样使用:

git export ~/the/destination/dir

如果目标目录已存在,则需要添加 -f 要么 --force

安装简单;把脚本放在你的某个地方 PATH,并确保它是可执行的。

github存储库 git-export 


37
2017-10-16 17:17



这个包装器不是平台无关的;它依赖于/ bin / sh。所以如果你在Windows上,这个解决方案 大概 不适合你。 - shovavnik
呃,这个脚本是57行文档,空格,设置,参数解析,只有一行实际上做了什么...... - Vladimir Panteleev


看起来这对于Git来说不像SVN那么严重。 Git只在存储库根目录中放置一个.git文件夹,而SVN在每个子目录中放置一个.svn文件夹。所以“svn export”避免了递归命令行魔术,而Git递归则没有必要。


35
2018-05-12 04:20



从SVN 1.7开始,也只有一个.svn文件夹: subversion.apache.org/docs/release-notes/1.7.html#single-db - kostmo
这不会消除svn export删除的任何其他构建文件。所以这绝对不是答案。 - ygoe
Downvoted因为答案无效。 - bahrep


相当于

svn export . otherpath

在现有的回购中是

git archive branchname | (cd otherpath; tar x)

相当于

svn export url otherpath

git archive --remote=url branchname | (cd otherpath; tar x)

26
2018-02-23 15:41



谢谢,这是我所遗漏的...也是,检查导出的时间戳(它们不会像文件一样保留),使用 git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -) ...但是,使用时间戳进行存档并不是很简单,所以我发布了一个 以下示例。 - sdaau
您可以使用tar选项而不是子shell,如下所示: git archive branchname | tar xC otherpath - James Moore
抬头说道 C tar的选项仅限GNU Tar。 - aredridel


我广泛使用git-submodules。 这个对我有用:

rsync -a ./FROM/ ./TO --exclude='.*'

21
2017-09-13 06:26



不会错过名称以点开头的文件,例如 .htaccess? - Greg Hewgill
一个很好的解决方案,我会改变--exclude ='。*'到--exclude ='。git *' - schmunk
--exclude-vcs如果你打算采取这种机智 - plod
可以./FROM/是一个远程回购? - Resist Design
作为一个FYI,我的副本 rsync 将参数列为 --cvs-exclude。此外,它仍然复制 .gitattributes 和 .gitignore - Ryan Ransford


如果您不排除文件 .gitattributes  export-ignore 然后试试 git checkout

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q

-F
  检查索引中的路径时,请勿在未合并时失败   项;相反,未合并的条目将被忽略。

-q
  避免冗长

此外,您可以获取任何分支或标记,或者从SVN中的特定提交修订版添加SHA1(Git中的SHA1等同于SVN中的修订号)

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./

/path/to/checkout/ 必须为空,Git不会删除任何文件,但会覆盖具有相同名称的文件而不会发出任何警告

更新: 为了避免斩首问题或者在使用checkout导出标签,分支或SHA1时保持工作存储库的完整性,您需要添加 -- ./ 最后

双击 -- 告诉git破折号后的所有内容都是路径或文件,并且在这种情况下也会告诉我 git checkout 不改变 HEAD

例子:

此命令将只获取libs目录以及 readme.txt 完全提交的文件

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt

这将创建(覆盖) my_file_2_behind_HEAD.txt 两个承诺在头后面 HEAD^2

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt

获得另一个分支的导出

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./

请注意 ./ 是相对于存储库的根目录


20
2017-12-10 17:17



实际上,在众多其他人和赞成之中,这对我来说效果最好,没有任何压缩,与裸存储库(gitolite)一起工作正常。 - takeshin
请注意,SHA1签出将在存储库中创建“behead”问题 - user5286776117878
实际上@ITGabs,这不下载“.git”文件夹。所以下载的文件夹不是git存储库,所以从技术上来说它不是“斩首” - Fabio Marreco
@FabioMarreco behead问题出现在存储库而不是导出/下载的文件中,我正在更新答案以获取更多详细信息 - user5286776117878
这对我很有用。但起初我得到了“Not a git repository”错误消息。然后我发现“/ path / to / repo /”必须指向.git文件夹。所以这工作: - git-dir = / path / to / repo / .git - philburk


这将复制所有内容,减去.dot文件。我使用它来将git克隆的项目导出到我的web应用程序的git repo而没有.git的东西。

cp -R ./path-to-git-repo / path / to / destination /

普通的老bash工作得很好:)


16
2018-01-22 17:31



为什么不直接推送到远程?甚至比bash更简单。 - nurettin
那些属于Web应用程序的文件及其名称以dot开头? :)想想.htaccess - Artur
有时你也想忽略它的内容 .gitignore,这不会。 - bfred.it