tags:

views:

28915

answers:

14

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

+4  A: 

Uh, this is a bit of a non-problem isn't it? You listed three trivial solutions to it...

Pick one, stick it in a shell-script, name it git-export and be done with it.

with large repositories, using git clone is considerably more resource-intensive than git checkout-index. Wrapping a bad solution in a shell script doesn't make it much better.
p00ya
+7  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

jperras
I think the confusion is the phrase "read the desired tree into the index".
davetron5000
+43  A: 

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

git checkout-index -a -f --prefix=/destination/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.

Greg Hewgill
...and DON'T FORGET THE SLASH AT THE END, or you won't have the desired effect ;)
conny
Isn't the index just a name for the "staging" area? How's it that the tree is already there? I thought you can only add stuff manually to it with `git add`
hasen j
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.
Greg Hewgill
seems that this is equivalent to `git archive HEAD`
takeshin
@conny: read your comment, forgot about it and ran the command without a trailing slash. tip: follow conny's advice -.-
Znarkus
+1  A: 

Just for posterity - as I'm also going through a process of being an SVN user attempting to get up to speed on git, this is a pretty good quick reference on SVN-Git command analogues.

ramanman
A: 

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.

skiphoppy
The project I had in mind isn't a code project; it happens to be more along the lines of a web site project.
Greg Hewgill
+127  A: 

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

git help archive for more details, it's quite flexible.

Charles Bailey
ZIP archive: `git archive --format zip --output /full/path master`
Stream
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 http://feeding.cloud.geek.nz/2010/02/excluding-files-from-git-archive.html
mj1531
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'.)
anotherAlan
+18  A: 

I've written a simple wrapper around git-checkout-index that you can use like this:

git export ~/the/destination/dir

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

Daniel Schierbeck
+21  A: 

git-archive also works with remote repository.

git-archive --format=tar --remote=ssh://remote_server/remote_repository master | tar -xf -
Somov Alexander
This one is the option I like best. It has the additional benefit that it also works on bare repositories.
innaM
+4  A: 

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.

kostmo
A: 

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:

#!/bin/sh
[ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1
REPOSITORY=$1
DESTINATION=$2
TMPNAME="/tmp/$(basename $REPOSITORY).$$"
git clone $REPOSITORY $TMPNAME
rm -rf $TMPNAME/.git
mkdir -p $DESTINATION
cp -r $TMPNAME/* $DESTINATION
rm -rf $TMPNAME
troelskn
Charles Bailey
I couldn't get read-tree to work from a remote repository, and the archive solution doesn't work with github.
troelskn
A: 

All the answers given involve cloning the repository locally first.

Does there exist a method to export directly from a remote repository to a local directory, only copying the objects required to do so (ie, do not fetch the entire repository)?

pauldoo
If you want to ask a question the ask a question, don't provide an answer that isn'tan answer. In answer to your 'question' you can use `--remote` with `git archive`.
Charles Bailey
A: 

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.

gitss() {
    URL=[url:path]

    TMPFILE="`/bin/tempfile`"
    if [ "$1" = "" ]; then
        echo -e "Use: gitss repo [tree/commit]\n"
        return
    fi
    if [ "$2" = "" ]; then
        TREEISH="HEAD"
    else
        TREEISH="$2"
    fi
    echo "Getting $1/$TREEISH..."
    git archive --format=zip --remote=$URL/$1 $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n"
    rm $TMPFILE
}

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

ss = !env GIT_TMPFILE="`/bin/tempfile`" sh -c 'git archive --format=zip --remote=[url:path]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -
RkG
A: 

RE the original question: "I've been wondering whether there is a good "git export" solution that creates a copy of a tree without the .git repository directory."

So apparently the answer is "no."

There are a number of more/less annoying workarounds, but the inability to export the CONTENTS of the repository in plain uncompressed form, without creating a repository first and without including repository artifacts (ala SVN export) is a glaring hole in git functionality.

Sighhhhhh...

rnr Tom
+2  A: 

I just want to point out that in the case that you are

  1. exporting a sub folder of the repository (that's how I used to use SVN export feature)
  2. are OK with copying everything from that folder to the deployment destination
  3. and since you already have a copy of the entire repository in place.

Then you can just use cp foo [destination] instead of the mentioned git-archive master foo | -x -C [destination].

DKinzer