Do a “git export” (like “svn export”)?
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.
-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.
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:
git clonefollowed by removing the
git checkout-indexalludes to this functionality but starts with "Just read the desired tree into the index..." which I'm not entirely sure how to do.
git-exportis a third party script that essentially does a
git cloneinto 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.
A special case answer if the repository is hosted on GitHub.
As far as I know Github does not allow
archive --remote. Although GitHub is svn compatible and they do have all git repos
svn accessible so you could just use
svn export like you normally would with a few adjustments to your GitHub url.
For example to export an entire repository, notice how
trunk in the URL replaces
master (or whatever the project's HEAD branch is set to):
svn export https://github.com/username/repo-name/trunk/
And you can export a single file or even a certain path or folder:
svn export https://github.com/username/repo-name/trunk/src/lib/folder
HEAD branch or master branch will be available using
svn ls https://github.com/jquery/jquery/trunk
HEAD branches will be accessible under
svn ls https://github.com/jquery/jquery/branches/2.1-stable
All tags under
/tags/ in the same fashion:
svn ls https://github.com/jquery/jquery/tags/2.1.3
The option 1 sounds not too efficient. What if there is no space in the client to do a clone and then remove the
Today I found myself trying to do this, where the client is a Raspberry Pi with almost no space left. Furthermore, I also want to exclude some heavy folder from the repository.
Option 2 and others answers here do not help in this scenario. Neither
git archive (because require to commit a
.gitattributes file, and I don't want to save this exclusion in the repository).
Here I share my solution, similar to option 3, but without the need of
tmp=`mktemp` git ls-tree --name-only -r HEAD > $tmp rsync -avz --files-from=$tmp --exclude='fonts/*' . raspberry:
rsync line for an equivalent line for compress will also work as a
git archive but with a sort of exclusion option (as is asked here).
Yes, this is a clean and neat command to archive your code without any git inclusion in the archive and is good to pass around without worrying about any git commit history.
git archive --format zip --output /full/path/to/zipfile.zip master
I think @Aredridel's post was closest, but there's a bit more to that - so I will add this here; the thing is, in
svn, if you're in a subfolder of a repo, and you do:
/media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir
svn will export all files that are under revision control (they could have also freshly Added; or Modified status) - and if you have other "junk" in that directory (and I'm not counting
.svn subfolders here, but visible stuff like
.o files), it will not be exported; only those files registered by the SVN repo will be exported. For me, one nice thing is that this export also includes files with local changes that have not been committed yet; and another nice thing is that the timestamps of the exported files are the same as the original ones. Or, as
svn help export puts it:
- Exports a clean directory tree from the working copy specified by PATH1, at revision REV if it is given, otherwise at WORKING, into PATH2. ... If REV is not specified, all local changes will be preserved. Files not under version control will not be copied.
To realize that
git will not preserve the timestamps, compare the output of these commands (in a subfolder of a
git repo of your choice):
/media/disk/git_svn/subdir$ ls -la .
/media/disk/git_svn/subdir$ git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)
... and I, in any case, notice that
git archive causes all the timestamps of the archived file to be the same!
git help archive says:
git archive behaves differently when given a tree ID versus when given a commit ID or tag ID. In the first case the current time is used as the modification time of each file in the archive. In the latter case the commit time as recorded in the referenced commit object is used instead.
... but apparently both cases set the "modification time of each file"; thereby not preserving the actual timestamps of those files!
So, in order to also preserve the timestamps, here is a
bash script, which is actually a "one-liner", albeit somewhat complicated - so below it is posted in multiple lines:
/media/disk/git_svn/subdir$ git archive --format=tar master | (tar tf -) | (\ DEST="/media/diskC/tmp/subdirB"; \ CWD="$PWD"; \ while read line; do \ DN=$(dirname "$line"); BN=$(basename "$line"); \ SRD="$CWD"; TGD="$DEST"; \ if [ "$DN" != "." ]; then \ SRD="$SRD/$DN" ; TGD="$TGD/$DN" ; \ if [ ! -d "$TGD" ] ; then \ CMD="mkdir \"$TGD\"; touch -r \"$SRD\" \"$TGD\""; \ echo "$CMD"; \ eval "$CMD"; \ fi; \ fi; \ CMD="cp -a \"$SRD/$BN\" \"$TGD/\""; \ echo "$CMD"; \ eval "$CMD"; \ done \ )
Note that it is assumed that you're exporting the contents in "current" directory (above,
/media/disk/git_svn/subdir) - and the destination you're exporting into is somewhat inconveniently placed, but it is in
DEST environment variable. Note that with this script; you must create the
DEST directory manually yourself, before running the above script.
After the script is ran, you should be able to compare:
ls -la /media/disk/git_svn/subdir ls -la /media/diskC/tmp/subdirB # DEST
... and hopefully see the same timestamps (for those files that were under version control).
Hope this helps someone,
As simple as clone then delete the .git folder:
git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git
If you need submodules as well, this should do the trick: https://github.com/meitar/git-archive-all.sh/wiki
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
Installation is simple; just drop the script somewhere in your
PATH, and make sure it's executable.
I have hit this page frequently when looking for a way to export a git repository. My answer to this question considers three properties that svn export has by design compared to git, since svn follows a centralized repository approach:
- It minimizes the traffic to a remote repository location by not exporting all revisions
- It does not include meta information in the export directory
Exporting a certain branch using svn is accomplished by specifying the appropriate path
git clone --depth 1 --branch master git://git.somewhere destination_path rm -rf destination_path/.git
When building a certain release it is useful to clone a stable branch as for example
--branch stable or
For GitHub users, the
git archive --remote method won't work directly, as the export URL is ephemeral. You must ask GitHub for the URL, then download that URL.
curl makes that easy:
curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -
This will give you the exported code in a local directory. Example:
$ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf - $ ls jpic-bashworks-34f4441/ break conf docs hack LICENSE mlog module mpd mtests os README.rst remote todo vcs vps wepcrack
If you want the code put into a specific, existing directory (rather than the random one from github):
curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \ tar xzC /path/you/want --strip 1
As I understand the question, it it more about downloading just certain state from the server, without history, and without data of other branches, rather than extracting a state from a local repository (as many anwsers here do).
That can be done like this:
git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \ && rm -rf repo/.git/
--single-branchis available since Git 1.7.10 (April 2012).
--depthis (was?) reportedly faulty, but for the case of an export, the mentioned issues should not matter.
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
If you're not excluding files with
export-ignore then try
mkdir /path/to/checkout/ git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q
When checking out paths from the index, do not fail upon unmerged entries; instead, unmerged entries are ignored.
Additionally you can get any Branch or Tag or from a specific Commit Revision like in SVN just adding the SHA1 (SHA1 in Git is the equivalent to the Revision Number in SVN)
mkdir /path/to/checkout/ git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./
/path/to/checkout/ must be empty, Git will not delete any file, but will overwrite files with the same name without any warning
To avoid the beheaded problem or to leave intact the working repository when using checkout for export with tags, branches or SHA1, you need to add
-- ./ at the end
The double dash
-- tells git that everything after the dashes are paths or files, and also in this case tells
git checkout to not change the
This command will get just the libs directory and also the
readme.txt file from that exactly commit
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt
This will create(overwrite)
my_file_2_behind_HEAD.txt two commits behind the head
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt
To get the export of another branch
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./
./ is relative to the root of the repository
The equivalent of
svn export . otherpath
inside an existing repo is
git archive branchname | (cd otherpath; tar x)
The equivalent of
svn export url otherpath
git archive --remote=url branchname | (cd otherpath; tar x)
If you want something that works with submodules this might be worth a go.
- MASTER_DIR = a checkout with your submodules checked out also
- DEST_DIR = where this export will end up
- If you have rsync, I think you'd be able to do the same thing with even less ball ache.
- You need to run this from the parent directory of MASTER_DIR ( i.e from MASTER_DIR cd .. )
- DEST_DIR is assumed to have been created. This is pretty easy to modify to include the creation of a DEST_DIR if you wanted to
cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz --exclude='.git*' . && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz