我一直想知道是否有一个好的“git导出”解决方案可以创建没有 .git
存储库目录的树的副本。 我至少知道三种方法:
-
git clone
,然后删除.git
存储库目录。
-
git checkout-index
暗示了此功能,但以“将所需的树读入索引...”开头,我不完全确定该怎么做。
-
git-export
是一个第三方脚本,本质上是将 git clone
复制到临时位置,然后将 rsync --exclude='.git'
复制到最终目的地。
这些解决方案都没有让我真正满意。 与 svn export 最接近的可能是选项 1,因为两者都要求目标目录首先为空。 但选项 2 似乎更好,假设我可以弄清楚将树读入索引意味着什么。
I've been wondering whether there is a good "git export" solution that creates a copy of a tree without the .git
repository directory. There are at least three methods I know of:
git clone
followed by removing the .git
repository directory.
git checkout-index
alludes to this functionality but starts with "Just read the desired tree into the index..." which I'm not entirely sure how to do.
git-export
is a third-party script that essentially does a git clone
into a temporary location followed by rsync --exclude='.git'
into the final destination.
None of these solutions really strike me as being satisfactory. The closest one to svn export
might be option 1, because both require the target directory to be empty first. But option 2 seems even better, assuming I can figure out what it means to read a tree into the index.
发布评论
评论(30)
实现这一目标的最简单方法可能是使用
git archive
。 如果你真的只需要扩展树,你可以这样做。大多数时候,我需要从 git '导出' 一些东西,无论如何我都想要一个压缩档案,所以我会做这样的事情。
ZIP 存档:
git help archive
了解更多详细信息,非常详细灵活的。请注意,即使存档不包含 .git 目录,它也会包含其他隐藏的 git 特定文件,如 .gitignore、.gitattributes 等。如果您不希望它们出现在存档中,请确保您使用 .gitattributes 文件中的 export-ignore 属性,并在归档之前提交该属性。 了解更多...
注意:如果您有兴趣导出索引,则命令是
(有关更多详细信息,请参阅 Greg'sanswer)
下面是在 Linux 上使用 libchrony 的真实示例:
这些命令生成一个 zip 文件并将其解压到
$HOME/dev/libchrony
中。 我们可以使用以下命令查看存档:Probably the simplest way to achieve this is with
git archive
. If you really need just the expanded tree you can do something like this.Most of the time that I need to 'export' something from git, I want a compressed archive in any case so I do something like this.
ZIP archive:
git help archive
for more details, it's quite flexible.Be aware that even though the archive will not contain the .git directory, it will, however, contain other hidden git-specific files like .gitignore, .gitattributes, etc. If you don't want them in the archive, make sure you use the export-ignore attribute in a .gitattributes file and commit this before doing your archive. Read more...
Note: If you are interested in exporting the index, the command is
(See Greg's answer for more details)
Here's a real-world example using libchrony on Linux:
Those commands produce a zip file and extract it into
$HOME/dev/libchrony
. We can peek into the archive using:我明白了选项2的含义。 从存储库中,您可以执行以下操作:
路径末尾的斜杠很重要,否则将导致文件位于 /destination 中,前缀为“path”。
由于在正常情况下索引包含存储库的内容,因此无需执行任何特殊操作即可“将所需的树读入索引”。 它已经在那里了。
需要
-a
标志来检查索引中的所有文件(我不确定在这种情况下省略此标志意味着什么,因为它不执行我想要的操作)。-f
标志强制覆盖输出中的任何现有文件,而此命令通常不会执行此操作。这似乎是我正在寻找的那种“git 导出”。
I found out what option 2 means. From a repository, you can do:
The slash at the end of the path is important, otherwise it will result in the files being in /destination with a prefix of 'path'.
Since in a normal situation the index contains the contents of the repository, there is nothing special to do to "read the desired tree into the index". It's already there.
The
-a
flag is required to check out all files in the index (I'm not sure what it means to omit this flag in this situation, since it doesn't do what I want). The-f
flag forces overwriting any existing files in the output, which this command doesn't normally do.This appears to be the sort of "git export" I was looking for.
git archive
也适用于远程存储库。要导出存储库内的特定路径,请添加任意多个路径作为 git 的最后一个参数,例如:
git archive
also works with remote repository.To export particular path inside the repo add as many paths as you wish as last argument to git, e.g.:
如果存储库托管在 GitHub 上,则为特殊情况答案。
只需使用
svn导出
。据我所知,Github 不允许
archive --remote
。 尽管 GitHub 是 svn 兼容 并且他们确实拥有所有 git 存储库svn< /code> 可访问,因此您可以像平常一样使用 svn export ,只需对 GitHub url 进行一些调整即可。
例如,要导出整个存储库,请注意 URL 中的
trunk
如何替换master
(或任何 项目的 HEAD 分支设置为):您可以导出单个文件甚至某个路径或文件夹:
示例为 jQuery JavaScript 库
HEAD
分支或 master 分支将可使用 < code>trunk:非
HEAD
分支将在/branches/
下访问:所有标签 > 以同样的方式在
/tags/
下:A special case answer if the repository is hosted on GitHub.
Just use
svn export
.As far as I know Github does not allow
archive --remote
. Although GitHub is svn compatible and they do have all git repossvn
accessible so you could just usesvn export
like you normally would with a few adjustments to your GitHub url.For example to export an entire repository, notice how
trunk
in the URL replacesmaster
(or whatever the project's HEAD branch is set to):And you can export a single file or even a certain path or folder:
Example with jQuery JavaScript Library
The
HEAD
branch or master branch will be available usingtrunk
:The non-
HEAD
branches will be accessible under/branches/
:All tags under
/tags/
in the same fashion:来自 Git 手册< /a>:
使用 git-checkout-index 来“导出整个树”
前缀功能基本上使得使用 git-checkout-index 作为“导出为树”功能变得微不足道。 只需将所需的树读入索引,然后执行:
$ git checkout-index --prefix=git-export-dir/ -a
From the Git Manual:
Using git-checkout-index to "export an entire tree"
The prefix ability basically makes it trivial to use git-checkout-index as an "export as tree" function. Just read the desired tree into the index, and do:
$ git checkout-index --prefix=git-export-dir/ -a
我已经为
git-checkout-index
编写了一个简单的包装器,您可以像这样使用:如果目标目录已经存在,则需要添加
-f
或--force
。安装简单; 只需将脚本放在
PATH
中的某个位置,并确保它是可执行的。git-export
的 github 存储库I've written a simple wrapper around
git-checkout-index
that you can use like this:If the destination directory already exists, you'll need to add
-f
or--force
.Installation is simple; just drop the script somewhere in your
PATH
, and make sure it's executable.The github repository for
git-export
看来 Git 的问题比 SVN 的问题要小。 Git 仅在存储库根目录中放置一个 .git 文件夹,而 SVN 在每个子目录中放置一个 .svn 文件夹。 因此“svn export”避免了递归命令行魔法,而使用 Git 则不需要递归。
It appears that this is less of an issue with Git than SVN. Git only puts a .git folder in the repository root, whereas SVN puts a .svn folder in every subdirectory. So "svn export" avoids recursive command-line magic, whereas with Git recursion is not necessary.
相当于
在现有存储库中是
相当于
是
The equivalent of
inside an existing repo is
The equivalent of
is
如果您不排除带有
.gitattributes
export-ignore
的文件,请尝试git checkout
和
此外,您可以从特定的提交修订中获取任何分支或标签,例如在 SVN 中只需添加 SHA1(Git 中的 SHA1 相当于 SVN 中的修订号)
/path/to/checkout/ 必须为空,Git 不会删除任何文件,但会覆盖同名文件且没有任何警告
更新:
请注意上例中末尾的
-- ./
。 这是为了避免使用带有标签、分支或 SHA1 的 checkout 导出时出现斩首问题。 双破折号--
告诉 git 破折号后面的所有内容都是路径或文件,并且在这种情况下告诉git checkout
不要更改HEAD
。 路径./
相对于存储库的根目录。其他示例:
此命令将仅获取 libs 目录以及来自另一个分支的
readme.txt
文件这将在 head 后面创建(覆盖)
my_file_2_behind_HEAD.txt
两次提交 <代码>HEAD^2更新2:
为了避免在使用自定义 SHA1(或标签、分支)时出现索引更改问题,请强制 Git 使用临时索引文件
(注意:使用
GIT_INDEX_FILE
的绝对路径更安全)。If you're not excluding files with
.gitattributes
export-ignore
then trygit checkout
and
Additionally you can get any Branch or Tag or from a specific Commit Revision like in SVN just adding the SHA1 (SHA1 in Git is the equivalent to the Revision Number in SVN)
The
/path/to/checkout/
must be empty, Git will not delete any file, but will overwrite files with the same name without any warningUPDATE:
Note
-- ./
at the end in the above example. It is to avoid the beheaded problem when using checkout for export with tags, branches or SHA1. The double dash--
tells git that everything after the dashes are paths or files, and also in this case tellsgit checkout
to not change theHEAD
. The path./
is relative to the root of the repository.Other examples:
This command will get just the libs directory and also the
readme.txt
file from another branchThis will create(overwrite)
my_file_2_behind_HEAD.txt
two commits behind the headHEAD^2
UPDATE 2:
To avoid problem with changed index when using custom SHA1 (or tag, branch), force Git to use temporary index file
(Note: It's safer to use absolute path for
GIT_INDEX_FILE
).在寻找导出 git 存储库的方法时,我经常访问此页面。 我对这个问题的回答考虑了 svn export 与 git 相比在设计上具有的三个属性,因为 svn 遵循集中存储库方法:
它通过不导出所有修订来最小化远程存储库位置的流量
它不在导出目录中包含元信息
使用svn导出某个分支是通过指定适当的路径来完成的
在构建某个版本时,克隆稳定分支很有用,例如
--branch stable
或--branch release/0.9
。I have hit this page frequently when looking for a way to export a git repository. My answer to this question considers three properties that svn export has by design compared to git, since svn follows a centralized repository approach:
It minimizes the traffic to a remote repository location by not exporting all revisions
It does not include meta information in the export directory
Exporting a certain branch using svn is accomplished by specifying the appropriate path
When building a certain release it is useful to clone a stable branch as for example
--branch stable
or--branch release/0.9
.我广泛使用 git-submodules。
这对我有用:
I use git-submodules extensively.
This one works for me:
这将复制所有内容,减去 .dot 文件。 我用它来将 git 克隆项目导出到我的 Web 应用程序的 git 存储库中,而无需 .git 内容。
普通的旧 bash 效果很好:)
This will copy all contents, minus the .dot files. I use this to export git cloned projects into my web app's git repo without the .git stuff.
Plain old bash works just great :)
就像克隆然后删除 .git 文件夹一样简单:
As simple as clone then delete the .git folder:
对于 GitHub 用户,
git archive --remote
方法无法直接使用,因为 导出 URL 是临时的。 您必须向 GitHub 请求 URL,然后下载该 URL。curl
让这变得简单:这将为您提供本地目录中的导出代码。 示例:
编辑
如果您希望将代码放入特定的现有目录(而不是来自 github 的随机目录):
For GitHub users, the
git archive --remote
method won't work directly, as the export URL is ephemeral. You must ask GitHub for the URL, then download that URL.curl
makes that easy:This will give you the exported code in a local directory. Example:
Edit
If you want the code put into a specific, existing directory (rather than the random one from github):
是的,这是一个干净整洁的命令,用于存档代码,存档中不包含任何 git,并且很适合传递不用担心任何 git 提交历史记录。
Yes, this is a clean and neat command to archive your code without any git inclusion in the archive and is good to pass around without worrying about any git commit history.
我只是想指出,如果您要
然后你可以使用 cp foo [destination] 代替提到的 git-archive master foo | -x -C [目标]。
I just want to point out that in the case that you are
Then you can just use
cp foo [destination]
instead of the mentionedgit-archive master foo | -x -C [destination]
.您可以在任何提交时将远程存储库存档为 zip 文件。
You can archive a remote repo at any commit as zip file.
如果您想要与子模块一起使用的东西,这可能值得一试。
注意:
假设:
If you want something that works with submodules this might be worth a go.
Note:
Assumptions:
实际上,我的偏好是在 Makefile(或其他构建系统)中有一个 dist 目标,该目标导出代码的可分发存档(.tar.bz2、.zip、.jar 或任何合适的文件) )。 如果您碰巧使用 GNU 自动工具或 Perl 的 MakeMaker 系统,我认为这会自动为您提供。 如果没有,我强烈建议添加它。
ETA (2012-09-06):哇,严厉的反对票。 我仍然相信使用构建工具构建发行版比使用源代码控制工具更好。 我相信使用构建工具来构建工件。 在我目前的工作中,我们的主要产品是用 ant 目标构建的。 我们正在切换源代码控制系统,而这个 ant 目标的存在意味着迁移过程中减少了一些麻烦。
My preference would actually be to have a dist target in your Makefile (or other build system) that exports a distributable archive of your code (.tar.bz2, .zip, .jar, or whatever is appropriate). If you happen to be using GNU autotools or Perl's MakeMaker systems, I think this exists for you automatically. If not, I highly recommend adding it.
ETA (2012-09-06): Wow, harsh downvotes. I still believe it is better to build your distributions with your build tools rather than your source code control tool. I believe in building artifacts with build tools. In my current job, our main product is built with an ant target. We are in the midst of switching source code control systems, and the presence of this ant target means one less hassle in migration.
据我了解这个问题,它更多的是从服务器下载某些状态,没有历史记录,也没有其他分支的数据,而不是从本地存储库中提取状态(就像这里的许多 anwsers 所做的那样)。
可以这样完成:
--single-branch
自 Git 1.7.10(2012 年 4 月)起可用。--深度
是(曾经是?) 有缺陷,但对于导出的情况,上述问题应该无关紧要。As I understand the question, it it more about downloading just certain state from the server, without history, and without data of other branches, rather than extracting a state from a local repository (as many anwsers here do).
That can be done like this:
--single-branch
is available since Git 1.7.10 (April 2012).--depth
is (was?) reportedly faulty, but for the case of an export, the mentioned issues should not matter.git 导出的 Bash 实现。
我根据自己的功能对 .empty 文件创建和删除过程进行了分段,目的是在“git-archive”实现中重新使用它们(稍后发布)。
我还将“.gitattributes”文件添加到该进程中,以便从目标导出文件夹中删除不需要的文件。
流程更加详细,同时使“git-export”功能更加高效。
EMPTY_FILE=".空";
Bash-implementation of git-export.
I have segmented the .empty file creation and removal processes on their own function, with the purpose of re-using them in the 'git-archive' implementation (will be posted later on).
I have also added the '.gitattributes' file to the process in order to remove un-wanted files from the target export folder.
Included verbosity to the process while making the 'git-export' function more efficient.
EMPTY_FILE=".empty";
git 导出到 zip 存档,同时添加前缀(例如目录名称):
a git export to a zip archive while adding a prefix (e.g. directory name):
这会将一系列提交(C 到 G)中的文件复制到 tar 文件。 注意:这只会获取已提交的文件。 不是整个存储库。 从此处
示例提交 稍作修改历史
A --> B——> C--> D——> E--> F——> G--> H——> 我
git-diff-tree 手册页
-r--> 递归到子树
--no-commit-id --> git diff-tree 在适用时输出带有提交 ID 的行。 该标志抑制提交 ID 输出。
--仅名称--> 仅显示已更改文件的名称。
--diff-filter=ACMRT --> 仅选择这些文件。 请参阅此处获取完整的文件列表
C..G --> 此提交范围内的文件
C~ --> 包括来自提交 C 的文件。不仅仅是自提交 C 以来的文件
。 xargs tar -rf myTarFile --> 输出到焦油
This will copy the files in a range of commits (C to G) to a tar file. Note: this will only get the files commited. Not the entire repository. Slightly modified from Here
Example Commit History
A --> B --> C --> D --> E --> F --> G --> H --> I
git-diff-tree Manual Page
-r --> recurse into sub-trees
--no-commit-id --> git diff-tree outputs a line with the commit ID when applicable. This flag suppressed the commit ID output.
--name-only --> Show only names of changed files.
--diff-filter=ACMRT --> Select only these files. See here for full list of files
C..G --> Files in this range of commits
C~ --> Include files from Commit C. Not just files since Commit C.
| xargs tar -rf myTarFile --> outputs to tar
到目前为止,我见过的最简单的方法(也适用于 Windows)是 git bundle :
git bundle create /some/bundle/path.bundle --all
有关更多详细信息,请参阅此答案: 如何通过 USB 驱动器将 git 存储库从 Windows 计算机复制到 Linux 计算机?
By far the easiest way i've seen to do it (and works on windows as well) is
git bundle
:git bundle create /some/bundle/path.bundle --all
See this answer for more details: How can I copy my git repository from my windows machine to a linux machine via usb drive?
我需要这个作为部署脚本,但我无法使用上述任何方法。 相反,我想出了一个不同的解决方案:
I needed this for a deploy script and I couldn't use any of the above mentioned approaches. Instead I figured out a different solution:
方法很简单,这是 .bash_profile 的一个函数,它直接将存档解压到当前位置,首先配置您常用的 [url:path]。 注意:使用此功能可以避免克隆操作,它直接从远程存储库获取。
.gitconfig 的别名,需要相同的配置(请小心在 .git 项目中执行命令,它总是跳转到之前的基本目录 如此处所述,在解决此问题之前我个人更喜欢该功能
Doing it the easy way, this is a function for .bash_profile, it directly unzips the archive on current location, configure first your usual [url:path]. NOTE: With this function you avoid the clone operation, it gets directly from the remote repo.
Alias for .gitconfig, same configuration required (TAKE CARE executing the command inside .git projects, it ALWAYS jumps to the base dir previously as said here, until this is fixed I personally prefer the function
如果您在要创建导出的计算机上有存储库的本地副本,我有另一个可以正常工作的解决方案。 在这种情况下,移至此存储库目录,然后输入以下命令:
GIT_WORK_TREE=outputdirectory git checkout -f
如果您使用 git 存储库管理网站并希望在其中签出干净版本,则此命令特别有用<代码>/var/www/。 在这种情况下,请在
.git/hooks/post-receive
脚本中添加此命令(裸存储库上的hooks/post-receive
,更适合这种情况)I have another solution that works fine if you have a local copy of the repository on the machine where you would like to create the export. In this case move to this repository directory, and enter this command:
GIT_WORK_TREE=outputdirectory git checkout -f
This is particularly useful if you manage a website with a git repository and would like to checkout a clean version in
/var/www/
. In this case, add thiscommand in a.git/hooks/post-receive
script (hooks/post-receive
on a bare repository, which is more suitable in this situation)如果您还需要子模块,这应该可以解决问题:https://github。 com/meitar/git-archive-all.sh/wiki
If you need submodules as well, this should do the trick: https://github.com/meitar/git-archive-all.sh/wiki
我认为 @Arredridel 的帖子是最接近的,但还有更多内容 - 所以我将在这里添加它; 问题是,在 svn 中,如果您位于存储库的子文件夹中,并且执行以下操作:
那么 svn 将导出受修订控制的所有文件(它们可以还有新添加的;或修改状态) - 如果您在该目录中还有其他“垃圾”(这里我不计算
.svn
子文件夹,而是计算.o< 等可见内容) /code> 文件),它将不会被导出; 仅导出 SVN 存储库注册的文件。 对我来说,一件好事是此导出还包括尚未提交的具有本地更改的文件; 另一个好处是导出文件的时间戳与原始文件相同。 或者,正如 svn help export 所说:
要认识到 git 不会保留时间戳,请比较这些命令的输出(在您选择的 git 存储库的子文件夹中):
... 和:
..无论如何,我注意到
git archive
导致存档文件的所有时间戳都是相同的!git 帮助存档
说:...但显然这两种情况都设置了“每个文件的修改时间”; 因此不保留这些文件的实际时间戳!
因此,为了也保留时间戳,这里有一个
bash
脚本,它实际上是一个“单行”脚本,尽管有点复杂 - 所以下面它以多行形式发布:请注意,它是假设您正在导出“当前”目录中的内容(上面,
/media/disk/git_svn/subdir
) - 并且您要导出到的目标位置有点不方便,但它位于DEST
环境变量。 请注意,使用此脚本; 在运行上述脚本之前,您必须自己手动创建DEST
目录。运行脚本后,您应该能够比较:
...并希望看到相同的时间戳(对于那些受版本控制的文件)。
希望这对某人有帮助,
干杯!
I think @Aredridel's post was closest, but there's a bit more to that - so I will add this here; the thing is, in
svn
, if you're in a subfolder of a repo, and you do:then
svn
will export all files that are under revision control (they could have also freshly Added; or Modified status) - and if you have other "junk" in that directory (and I'm not counting.svn
subfolders here, but visible stuff like.o
files), it will not be exported; only those files registered by the SVN repo will be exported. For me, one nice thing is that this export also includes files with local changes that have not been committed yet; and another nice thing is that the timestamps of the exported files are the same as the original ones. Or, assvn help export
puts it:To realize that
git
will not preserve the timestamps, compare the output of these commands (in a subfolder of agit
repo of your choice):... and:
... and I, in any case, notice that
git archive
causes all the timestamps of the archived file to be the same!git help archive
says:... but apparently both cases set the "modification time of each file"; thereby not preserving the actual timestamps of those files!
So, in order to also preserve the timestamps, here is a
bash
script, which is actually a "one-liner", albeit somewhat complicated - so below it is posted in multiple lines:Note that it is assumed that you're exporting the contents in "current" directory (above,
/media/disk/git_svn/subdir
) - and the destination you're exporting into is somewhat inconveniently placed, but it is inDEST
environment variable. Note that with this script; you must create theDEST
directory manually yourself, before running the above script.After the script is ran, you should be able to compare:
... and hopefully see the same timestamps (for those files that were under version control).
Hope this helps someone,
Cheers!
选项 1 听起来不太有效。 如果客户端没有空间进行克隆并删除
.git
文件夹怎么办?今天我发现自己正在尝试这样做,其中客户端是几乎没有剩余空间的 Raspberry Pi。 此外,我还想从存储库中排除一些重文件夹。
选项 2 和此处的其他答案在这种情况下没有帮助。 都不是
git archive
(因为需要提交.gitattributes
文件,并且我不想将此排除项保存在存储库中)。在这里,我分享我的解决方案,类似于选项 3,但不需要
git clone
:将
rsync
行更改为压缩的等效行也将作为>git archive
但具有某种排除选项(如所要求的 这里)。The option 1 sounds not too efficient. What if there is no space in the client to do a clone and then remove the
.git
folder?Today I found myself trying to do this, where the client is a Raspberry Pi with almost no space left. Furthermore, I also want to exclude some heavy folder from the repository.
Option 2 and others answers here do not help in this scenario. Neither
git archive
(because require to commit a.gitattributes
file, and I don't want to save this exclusion in the repository).Here I share my solution, similar to option 3, but without the need of
git clone
:Changing the
rsync
line for an equivalent line for compress will also work as agit archive
but with a sort of exclusion option (as is asked here).