【问题标题】:How do I exclude files from git archive?如何从 git 存档中排除文件?
【发布时间】:2016-12-08 19:56:49
【问题描述】:

给定一个简单的测试存储库,其中包含两个文件ab,我可以得到一个特定文件的列表:

$ git ls-files a
a

或不包括特定文件的所有文件的列表:

$ git ls-files . ':!b'
a

我可以创建特定文件的存档:

$ git archive HEAD a | tar tf -
a

但我无法创建除特定文件之外的所有文件的存档:

$ git archive HEAD . ':!b' | tar tf -
a
b

在我的真实存储库中,使用特定文件存档的选项对我来说不是一个选项,因为它超过了最大命令行参数长度。

我知道我可以通过export-ignore 属性将要排除的文件列表存储在.gitattributes 中,但该列表是动态生成的。我可以自动更改文件,但在另一次提交之前不会获取更改。

是否还有其他无需再次提交即可工作的调用?

【问题讨论】:

    标签: git git-archive


    【解决方案1】:

    一个可能的解决方案在于git archive 想要一个树状存档。

    您正在传递它HEAD(可能是最常见的选择)。为了实现你的意思,这个 ref 会自动解析为它指向的对象——很明显,这将是一个提交。并且提交对象被解析为附加到它的树对象。所以你得到了当前提交的内容。到目前为止,很明显。

    但是你可以传递任何你想要的树对象!这有什么帮助?好吧,您始终可以使用 git write-tree 从索引的当前状态创建一个树对象——它返回它刚刚在标准输出上创建的树对象的 SHA1。您不必创建提交或类似的东西。

    所以你可以在 tarball 中只使用 git rm --cached 任何你不想要的东西,然后创建一个树对象传递给 git archive。由于您不关心树对象,因此您可以将其组合到 git archive 命令中:

    git archive $( git write-tree )
    

    之后,您可以git reset --hard 并继续前进。

    大家一起:

    git rm --cached foo bar baz
    git archive $( git write-tree )
    git reset --all
    

    【讨论】:

      【解决方案2】:

      使用 Git 2.20 版(Windows)和 Gitolite 服务器(未知版本),这对我来说可以排除名为“b”的文件和文件夹:

      git archive HEAD . ":!b" | tar tf -
      

      这也有效:

      git archive HEAD . ":(exclude)b" | tar tf -
      

      注意,我在 Windows 平台上必须使用双引号,其他平台不确定。

      【讨论】:

        【解决方案3】:

        除了将export-ignore 放入(已提交).gitattributes 之外,您还可以将其放入(未提交)$GIT_DIR/info/attributes 文件中。或者,不提交 .gitattributes 并使用 --worktree-attributes 选项,这也可能不太好,因为它会使工作树变脏。

        【讨论】:

          【解决方案4】:

          我认为您几乎成功了:可以从多个位置读取属性,.gitattributes 只是其中最常见的。第二个——考虑到每个存储库的配置——是$GIT_DIR/info/attributes

          引用手册:

          请注意,属性默认取自 .gitattributes 文件中的 正在归档的树。如果你想调整输出的方式 事后生成(例如,您在未添加适当的 export-ignore 在其.gitattributes),调整签出的.gitattributes 文件 根据需要使用--worktree-attributes 选项。或者,您可以保留 在归档您的任何树时应该应用的必要属性 $GIT_DIR/info/attributes 文件。

          因此,如果可能,请将您的列表粘贴到该文件中,然后执行git archive

          另一种方法是不使用git archive,而仅使用tar 传递tar 接受文件的--exclude-from 命令行选项的工作树。这不适用于裸存储库,但如果您可以在归档之前检查内容,这可以通过使用正确的 $GIT_INDEX_FILE$GIT_WORK_TREE env 提供的 git read-treegit checkout-index 来完成。变量。

          另一种可能的解决方法是颠倒该方法:tar(至少是 GNU tar)支持一个鲜为人知的选项,即能够从管道中的存档中删除内容。

          基本上是可以的

           $ tar -C a_path -c -f - . \
             | tar -f - --wildcards --delete '*.pdf' >result.tar
          

          以便管道中的第一个 tar 归档所有内容,而第二个传递所有内容,但匹配 *.pdf shell glob 模式的文件除外。

          因此,如果使用 shell glob 指定要删除的文件可以满足命令行限制,只需将 git archive 的输出通过管道传输到 tar 进程,从而删除不需要的内容。

          【讨论】:

          • 感谢您的详细回答。我认为.git/info/attributes对我来说不一定是最合乎逻辑的方法,但它最适合我已经拥有的东西,如果我将来需要更多东西,我可以将其更改为tar --delete
          【解决方案5】:

          您可以创建一个 tar 然后删除不需要在里面的文件夹和文件

          git archive HEAD -o archive.tar
          tar -f archive.tar --delete listoffiles1
          tar -f archive.tar --delete listoffiles2
          tar -f archive.tar --delete listoffiles..
          tar -f archive.tar --delete listoffilesN
          

          这样你可以分割你的命令行以保持在最大 cli 参数长度以下

          【讨论】:

            猜你喜欢
            • 2011-09-11
            • 2016-08-13
            • 2023-03-20
            • 2019-08-16
            • 2018-10-13
            • 1970-01-01
            • 2019-11-09
            • 2011-04-07
            • 1970-01-01
            相关资源
            最近更新 更多