Search code examples
gitexportgit-archivesvn-export

Do a "git export" (like "svn export")?


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:

  1. git clone followed by removing the .git repository directory.
  2. 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.
  3. 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.


Solution

  • 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.

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

    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.

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

    ZIP archive:

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

    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

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

    (See Greg's answer for more details)


    Here's a real-world example using libchrony on Linux:

    mkdir $HOME/dev
    cd $HOME/dev
    pushd /tmp
    git clone https://gitlab.com/chrony/libchrony.git
    cd libchrony
    BRANCH=$(git rev-parse --abbrev-ref HEAD)
    git archive -o ../libchrony.zip --prefix="libchrony/" $BRANCH
    popd
    unzip /tmp/libchrony.zip
    

    Those commands produce a zip file and extract it into $HOME/dev/libchrony. We can peek into the archive using:

    $ unzip -v /tmp/libchrony
    Archive:  /tmp/libchrony.zip
    e0a3807f770b56f6b0e9833254baa7c4fc13564b
     Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
    --------  ------  ------- ---- ---------- ----- --------  ----
           0  Stored        0   0% 2023-07-20 09:37 00000000  libchrony/
          49  Defl:N       47   4% 2023-07-20 09:37 37c3f2e2  libchrony/.gitignore
       26530  Defl:N     9350  65% 2023-07-20 09:37 5622583e  libchrony/COPYING
         961  Defl:N      467  51% 2023-07-20 09:37 da9221e3  libchrony/Makefile
         475  Defl:N      304  36% 2023-07-20 09:37 cae27f70  libchrony/README.adoc
        3313  Defl:N     1119  66% 2023-07-20 09:37 37eb110f  libchrony/chrony.h
        7673  Defl:N     2261  71% 2023-07-20 09:37 5d455a52  libchrony/client.c
        6190  Defl:N     2093  66% 2023-07-20 09:37 7ea9d81b  libchrony/example-reports.c
       16348  Defl:N     3855  76% 2023-07-20 09:37 e82f5fe3  libchrony/message.c
        2946  Defl:N     1099  63% 2023-07-20 09:37 945ee82b  libchrony/message.h
    --------          -------  ---                            -------
       64485            20595  68%                            10 files