git可以将zip文件作为目录和zip文件中的文件视为blob吗?

Jon*_*erg 65 git zip msysgit

场景

想象一下,我被迫使用一些总是存储在.zip文件中的文件.zip中的一些文件是小文本文件并经常更改,而其他文件更大但幸运的是相当静态(例如图像).

如果我想将这些zip文件放在git存储库中,每个zip都被视为一个blob,所以每当我提交存储库时,就会增加zip文件的大小...即使只有一个小文本文件在里面改变了!

为什么这是现实的

MS Word 2007/2010 .docx和Excel .xlsx文件是ZIP文件...

我想要的是

是否有任何机会告诉git不要将拉链视为文件,而是作为目录并将其内容视为文件?

优点

但是,它说不行吗?

我意识到如果没有额外的元数据,这将导致一些歧义:在git checkoutgit上必须决定是foo.zip/bar.txt在常规目录还是zip文件中创建文件.但是,我认为这可以通过配置选项解决.

两个想法如何完成(如果它还不存在)

  • 使用像git 这样的库minizip或者IO::Compress::Zip在git里面
  • 以某种方式添加一个文件系统层,以便git实际上将zip文件视为开始的目录

Jef*_*and 22

这不存在,但它可以很容易地存在于当前框架中.正如git在执行diff时显示二进制或ascii文件的行为不同,可以通过配置界面告诉它对某些文件类型提供特殊处理.

如果您不想更改代码库(虽然这是一个很酷的想法),您也可以通过使用预提交和后检查挂钩解压缩并存储文件来为自己编写脚本,然后在结账时将它们返回到.zip状态.您必须将操作限制为仅由指定的那些文件blob/index git add.

无论哪种方式都是一些工作 - 这只是一个问题,其他git赞扬是否知道发生了什么,并发挥得很好.

  • @Jonas你最终这样做过吗?你有机会发布一个可行的解决方案吗?我希望能够有效地跟踪 git 中电子表格的更改,而 CSV 不适合我们的目的。 (2认同)
  • 我刚写了一些钩子来做这件事.仍然在粗糙的边缘工作,但可能会有所帮助:https://github.com/ckrf/xlsx-git (2认同)

Sip*_*pey 13

不确定是否还有人对这个问题感兴趣.我面临同样的问题,这是我使用git文件过滤器的解决方案.

编辑:首先,我可能不是国家明确表态,但是这IS一个问题的任择议定书的问题!在评论之前阅读整个句子.此外,感谢@Toon Krijthe提供的建议,以澄清解决方案.

我的解决方案是使用过滤器将zip文件"扁平化"为单片扩展(可能是巨大的)文本文件.在git add/commit期间,zip文件将自动扩展为此文本格式以进行正常文本区分,并且在结帐时,它会再次自动压缩.

文本文件由记录组成,每个记录代表zip中的文件.所以你可以认为这个文本文件是原始zip的基于文本的图像.如果zip中的文件是契约中的文本,则将其复制到文本文件中; 否则,在复制到文本格式文件之前,它是base64编码的.这使文本文件始终保持为文本文件.

虽然这个过滤器不会使zip中的每个文件成为blob,但是文本文件是逐行映射的,这是diff的单位,而二进制文件的更改可以通过更新它们对应的base64来表示,我认为这相当于OP想象的是什么.

有关详细信息和原型代码,您可以阅读以下链接:

Zippey Git文件过滤器

此外,还有一个让我了解这个解决方案的地方: 文件过滤器的工作原理说明

  • 值得注意的是,您的存储库中没有“LICENSE”文件或任何等效文件。[无许可证 = 保留所有权利](https://choosealicense.com/no-permission/)。 (2认同)

Von*_*onC 11

使用bup(在GitMinutes#24中详细介绍)

它是唯一的git-like系统专门用来对付大(甚至是非常非常大)文件,这意味着一个zip文件的每个版本将只从它的增量增加(而不是一个完整的额外副本)回购

结果是一个实际的git repo,一个普通的Git命令可以读取.

我详细说明了bup" git with large files " 与Git的不同之处.


任何其他解决方法(如git-annex)都不完全令人满意,详见" git-annex大文件 ".


hoi*_*jui 7

重新压缩 ReZipDoc,类似于由sippey Zippey,允许处理与git的一个更好的方式ZIP文件。

这个怎么运作

添加/提交基于 ZIP 的文件时,Rezip 在将其添加到索引/提交之前将其解压缩并重新打包而不压缩。在未压缩的 ZIP 文件中,存档文件在其内容中按原样显示(在每个文件之前还有一些二进制元信息)。如果这些存档文件是纯文本文件,则此方法将与 git 一起使用。

好处

Rezip 相对于 Zippey 的主要好处是,存储在存储库中的实际文件仍然是 ZIP 文件。因此,在许多情况下,它仍然可以与相应的应用程序(例如 Open Office)一起工作,即使它是在不通过重新打包压缩过滤器的情况下获得的。

如何使用

在您的系统上安装过滤器:

mkdir -p ~/bin
cd ~/bin

# Download the filer executable
wget https://github.com/costerwi/rezip/blob/master/Rezip.class

# Install the add/commit filter
git config --global --replace-all filter.rezip.clean "java -cp ~/bin Rezip --store"

# (optionally) Install the checkout filter
    git config --global --add filter.rezip.smudge "java -cp ~/bin Rezip"
Run Code Online (Sandbox Code Playgroud)

使用存储库中的过滤器,在<repo-root>/.gitattributes文件中添加如下几行:

[attr]textual     diff merge text
[attr]rezip       filter=rezip textual

# MS Office
*.docx  rezip
*.xlsx  rezip
*.pptx  rezip
# OpenOffice
*.odt   rezip
*.ods   rezip
*.odp   rezip
# Misc
*.mcdx  rezip
*.slx   rezip
Run Code Online (Sandbox Code Playgroud)

textual部分是为了让这些文件在差异中实际显示为文本文件。


小智 5

http://tante.cc/2010/06/23/managing-zip-based-file-formats-in-git/

(注意:根据Ruben的评论,这只是关于获得适当的差异,而不是关于提交解压缩的文件.)

打开〜/ .gitconfig文件(如果已经存在则创建)并添加以下节:

[diff"zip"] textconv = unzip -c -a

它的作用是使用"unzip -c -a FILENAME"将zipfile转换为ASCII文本(解压缩-c解压缩到STDOUT).接下来是创建/修改文件REPOSITORY/.gitattributes并添加以下内容

*.pptx diff = zip

它告诉git使用配置中的zip-diffing描述来计算给定掩码的文件(在这种情况下,所有内容都以.pptx结尾).现在git diff自动解压缩文件并区分ASCII输出,这比仅仅"二进制文件不同"好一点.另一方面,对于pptx文件的相应XML的复杂混乱,它没有多大帮助,但对于包括文本的ZIP文件(例如源代码存档),这实际上非常方便.


Suk*_*mbu 5

这是我的方法:

  • 使用 Git diff 过滤器将存档文件替换为内容摘要

    git config filter.zip.clean "unzip -v %f | tail -n +4 | head -n -2 | awk '{ print \$7,\$8 }' | grep -vE /$ | LC_ALL=C sort -sfk 2,2"
    git config filter.zip.smudge "cat"
    git config filter.zip.required true
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用预提交挂钩提取并添加存档内容:

    #!/bin/sh
    #
    # Git archive extraction pre commit hook
    #
    # Created: 2021 by Vivien Richter <vivien-richter@outlook.de>
    # License: CC-BY-4.0
    # Version: 1.0.2
    
    # Configuration
    ARCHIVE_EXTENSIONS=$(cat .gitattributes | grep "zip" | tr -d [][:upper:] | cut -d " " -f1 | cut -d. -f2 | head -c -1 | tr "\n" "|")
    
    # Processing
    for STAGED_FILE in $(git diff --name-only --cached | grep -iE "\.($ARCHIVE_EXTENSIONS)$")
    do
        # Deletes the old archive content
        rm -rf ".$(basename $STAGED_FILE).content"
        # Extracts the archive content, if the archive itself is not removed
        if [ -f "$STAGED_FILE" ]; then
            unzip -o $STAGED_FILE -d "$(dirname $STAGED_FILE)/.$(basename $STAGED_FILE).content"
        fi
        # Adds extracted or deleted archive content to the stage
        git add "$(dirname $STAGED_FILE)/.$(basename $STAGED_FILE).content"
    done
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用结帐后挂钩再次打包档案以供使用:

    #!/bin/sh
    #
    # Git archive packing post checkout hook
    #
    # Created: 2021 by Vivien Richter <vivien-richter@outlook.de>
    # License: CC-BY-4.0
    # Version: 1.0.0
    
    # Configuration
    ARCHIVE_EXTENSIONS=$(cat .gitattributes | grep "zip" | tr -d [][:upper:] | cut -d " " -f1 | cut -d. -f2 | head -c -1 | tr "\n" "|")
    
    # Processing
    for EXTRACTED_ARCHIVE in $(git ls-tree -dr --full-tree --name-only HEAD | grep -iE "\.($ARCHIVE_EXTENSIONS)\.content$")
    do
        # Gets filename
        FILENAME=$(dirname $EXTRACTED_ARCHIVE)/$(basename $EXTRACTED_ARCHIVE | cut -d. -f2- | awk -F '.content' '{ print $1 }')
        # Removes the dummy archive file
        rm $FILENAME
        # Jumps into the extracted archive
        cd $EXTRACTED_ARCHIVE
        # Creates the real archive file
        zip -r9 ../"$FILENAME" $(find . -type f)
        # Jumps back
        cd ..
    done
    
    Run Code Online (Sandbox Code Playgroud)
  • 在文件中应用过滤器.gitattributes

    # Macro for all file types that should be treated as ZIP archives.
    [attr]zip text filter=zip
    
    # Forces `LF` as line endings for text based files inside ZIP archives.
    **/*.content/** text=auto eol=lf
    
    # OpenDocument
    *.[oO][dD][tT] zip
    *.[oO][dD][sS] zip
    *.[oO][dD][gG] zip
    *.[oO][dD][pP] zip
    *.[oO][dD][mM] zip
    
    # Krita
    *.[kK][rR][aA] zip
    
    # VRoid Studio
    *.[vV][rR][oO][iI][dD] zip
    *.[fF][vV][pP] zip
    
    Run Code Online (Sandbox Code Playgroud)
  • 向文件添加一些二进制处理.gitattributes

    # Macro for all binary files that should use Git LFS.
    [attr]bin -text filter=lfs diff=lfs merge=lfs lockable
    
    # Images
    *.[jJ][pP][gG] bin
    *.[jJ][pP][eE][gG] bin
    *.[pP][nN][gG] bin
    *.[aA][pP][nN][gG] bin
    *.[gG][iI][fF] bin
    *.[bB][mM][pP] bin
    *.[tT][gG][aA] bin
    *.[tT][iI][fF] bin
    *.[tT][iI][fF][fF] bin
    *.[sS][vV][gG][zZ] bin
    
    Run Code Online (Sandbox Code Playgroud)
  • 在文件中添加一些内容.gitignore

    # Auto generated LFS hooks
    .githooks/pre-push
    
    # Temporary files
    *~
    
    Run Code Online (Sandbox Code Playgroud)
  • 一些配置:

    1. 安装Git LFS
    2. 通过发出一次命令来准备 LFS git lfs install
    3. 设置 Git 过滤器。
    4. 通过发出命令来安装挂钩git config core.hooksPath .githooks
    5. 通过发出命令应用一次结账挂钩.githooks/post-checkout
    6. 通过发出命令应用一次过滤器git add -A

有关示例,请参见此处:Git 的 ZIP 处理

已知的问题