1

There is the git archive command - is there a way to create a tarball from a repo without making a commit? Essentially I just want to create tarball of the existing files (more importantly honoring gitignore). I assume git archive is looking for a commit - but I just want a snapshot of the code even for uncommitted changes.

Another way to do this would just be to write a program that will tar all the files and ignore what's in gitignore, but that would require writing that program.

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • Possible duplicate of [How to download the diffs present in the staging area in git](https://stackoverflow.com/questions/38816424/how-to-download-the-diffs-present-in-the-staging-area-in-git) – Joe May 03 '19 at 23:27
  • 3
    @Joe: that suggested duplicate is about making an archive that contains *only* the files that are *different* from the `HEAD` files. This question asks for an archive of what *would* be committed, if you committed. – torek May 04 '19 at 00:46

3 Answers3

2

git archive requires a treeish to use, which means you need a tree, commit, or tag. There's nothing preventing you from creating a temporary branch and a commit with the contents you want and archiving that.

Alternatively, if you're certain you don't care about the ignored files, you can run git clean -dffx and then use tar --exclude-vcs to package your archive. You could also skip the git clean invocation and try tar --exclude-vcs --exclude-vcs-ignores.

bk2204
  • 64,793
  • 6
  • 84
  • 100
1

The simple and easy and obviously correct way to do it is: just make a commit (as bk2204 suggests).

But, since git archive takes a <tree-ish>, you can do this without making a commit. Just make the tree part of a commit, which is half (or more) of an actual commit, and then use that:

git archive [additional options] $(git write-tree)

The issue here is that git write-tree will write whatever is in the index right now. This means you need to add all updated files to the index, even if you're not going to make a commit. You could do that with a temporary index, if you want to get extra fancy, but it's easier to just add -u first:

git add -u
git archive [additional options] $(git write-tree)

Another way to get the work-tree files into a commit, without making a commit yourself, is to use git stash to do the job. This will write the current work-tree to a new commit. Hence:

git stash push
git archive [additional options] refs/stash
git stash pop --index

would do the job, more or less. The less occurs when there is nothing to stash, in which case git stash push does nothing and you should not run git stash pop. In this particular case, you can archive HEAD—but it's annoying to detect whether git stash push did anything. You can add more layers of scripting to deal with that, but really, what's wrong with just committing now?

torek
  • 448,244
  • 59
  • 642
  • 775
  • I would just use a temporary branch but when I do that I end up working off that branch by accident because my script to return to previous branch fails or whatever. I was thinking about doing some sort of "virtual branch" which would not effect the state of the original repo at all somehow. To do this virtual branch I could take a shallow clone of the repo to some temp location on disk? – Alexander Mills May 04 '19 at 00:54
  • 1
    Also, `tar` takes a `T` command, you can do `git ls-files | tar Tcf - my.tar` to make the archive from the current worktree content without the write-tree, and `git ls-files --exclude-standard -oc | tar Tcf - my.tar` to tar up every file that `git add .` would see. – jthill May 04 '19 at 04:57
  • @jthill: depends on your version of tar, though it seems to be present in FreeBSD and Linux today at least. I don't recall it in Solaris or 4.4BSD tar... The 1997 POSIX standard doesn't have it: http://pubs.opengroup.org/onlinepubs/007908799/xcu/tar.html - but pax reads files from stdin, and can write tar format: http://pubs.opengroup.org/onlinepubs/007908799/xcu/pax.html – torek May 04 '19 at 16:59
  • I don't know whether the mingw environment includes `pax`; POSIX is very weird about pax/cpio/tar ... it doesn't include `tar` or `cpio` at all. But yeah, I think `git ls-files | pax -w my.tar` would do it too if the command's there. – jthill May 04 '19 at 18:39
1

In addition of making a commit, consider git bundle: it is like git archive... but with history.

You get one file (a bundle file), that you can copy around, and then clone back from.
See "Fully backup a git repo?" for more.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250