Categories
export git git-archive svn-export

Do a “git export” (like “svn export”)?

2491

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.

6

  • 1

    @rnrTom: See Somov’s answer. (there’s nothing “compressed” in a tar archive).

    – etarion

    May 23, 2012 at 15:59

  • 29

    @mrTom git archive --format zip --output "output.zip" master -0 will give you an uncompressed archive (-0 is the flag for uncompressed). git-scm.com/docs/git-archive.

    – user456814

    Sep 5, 2012 at 18:47

  • 8

    I concur with @mrTom, and I don’t think whether the archive is compressed or uncompressed is the main issue. With SVN, I can export a 250 kB subdirectory directly from remote repository (which could otherwise be 200 MB in size, excluding revisions) – and I will only hit the network for 250 kB (or so) download transfer. With git, archive has to be enabled on server (so I can’t try it) – clone --depth 1 from server may still retrieve a repo of say 25 MB, where the .git subfolder alone takes 15MB. Therefore, I’d still say answer is “no”.

    – sdaau

    Jan 28, 2013 at 14:59

  • 2

    Here is a nice and simple way: git archive -o latest.zip HEAD

    Jul 23, 2018 at 18:43

  • 4

    I’ve been using this question as the man-page for “git export” for years now, fyi.

    May 6, 2021 at 16:14

2520

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)

23

  • 205

    ZIP archive: git archive --format zip --output /full/path master

    – Vadim

    Apr 23, 2010 at 9:19

  • 226

    Be aware that the archive will not contain the .git directory, but will contain other hidden git-specific files like .gitignore, .gitattributes, etc. So if you don’t want them, make sure you use the export-ignore attribute in a .gitattributes file and commit this before doing your archive. See feeding.cloud.geek.nz/2010/02/…

    – mj1531

    Jul 6, 2010 at 14:55

  • 58

    To follow up on Streams’ note: you can add a ‘–prefix=something/’ string into the command to control the directory name that will be packed inside the zip. For example, if you use git archive --format zip --output /path/to/file.zip --prefix=newdir/ master the output will be called ‘file.zip’ but when you unpack it, the top level directory will be ‘newdir’. (If you omit the –prefix attribute, the top level dir would be ‘file’.)

    Sep 30, 2010 at 3:31


  • 93

    The easiest way: git archive -o latest.zip HEAD It create a Zip archive that contains the contents of the latest commit on the current branch. Note that the output format is inferred by the extension of the output file.

    – nacho4d

    Jun 1, 2011 at 10:47


  • 37

    It does not support git submodules 🙁

    – umpirsky

    Jul 21, 2011 at 7:59

341

I found out what option 2 means. From a repository, you can do:

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

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.

17

  • 77

    …and DON’T FORGET THE SLASH AT THE END, or you won’t have the desired effect 😉

    – conny

    Apr 8, 2009 at 20:48

  • 1

    The git add command changes content in the index, so whatever git status shows as “to be committed” is the differences between HEAD and the contents of the index.

    Aug 31, 2009 at 6:30

  • 7

    @conny: read your comment, forgot about it and ran the command without a trailing slash. tip: follow conny’s advice -.-

    – Znarkus

    Jun 24, 2010 at 16:55


  • 35

    +1 to conny’s advice. Also, don’t try to create ‘~/dest/’, as this creates a directory called ‘~’ in your working directory, rather than what you really wanted. Guess what happens when you mindlessly type rm -rf ~

    Apr 18, 2011 at 16:38

  • 5

    @KyleHeironimus – your warning about using ‘~/dest/` is true iff you use quotes around your prefix path which tells the shell not to perform tilde expansion. A dir called ~ (not '~' !) will be created in your working dir. There is nothing special about git checkout-index in this regard: The same is true of mkdir '~/dest' (don’t do that!). Yet another good reason to avoid file names that need quoting (e.g. that have a space in them) 🙂

    Sep 2, 2015 at 9:18


268

git archive also works with remote repository.

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

To export particular path inside the repo add as many paths as you wish as last argument to git, e.g.:

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

12

  • 6

    This one is the option I like best. It has the additional benefit that it also works on bare repositories.

    – innaM

    Aug 31, 2009 at 14:34

  • 6

    Am improved version is: git archive --format=tar --prefix=PROJECT_NAME/ [email protected]:PROJECT_NAME.git master | tar -xf - (ensures your archive is in a folder)

    – Nick

    Dec 15, 2011 at 15:57

  • 10

    Note: server must enable this feature.

    Dec 13, 2012 at 11:19


  • 14

    I tried : git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git master And got fatal: Operation not supported by protocol. Unexpected end of command stream.

    – andyf

    Jul 19, 2013 at 8:04

  • 10

    @andyf GitHub has its own way: curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf - per docs

    – bishop

    Jul 31, 2014 at 13:51