views:

623

answers:

6

I want to use something like the following command to create a tarball to deploy:

tar cjvf ~/deploy.tar.bz2 `git diff --name-only 0abc 1def`

The inner git diff command produces a list of files with relative including the relative path when i run it separately.

I'm running into two problems though, I need to be able to auto escape spaces in the output, so tar doesn't complain about files containing spaces and when the tar does get created, all the files have a duplicate 'hidden file' preceded by a '.' that don't show up with ls -al. These are OSX specific metafiles as noted by kch.

Anyway, does anyone know of the solution to these problems, or is there just a plain easier way to script this?

A: 

If size doesn't matter you could use git archive.

I'm not sure if it's possible to create a tarball containing only the differences between two commits.

hillu
That would work, but I want to avoid having to re-deploy files that don't contain changes.
Dana the Sane
A: 

You can try

eval tar cjvf ~/deploy.tar.bz2 `git diff --name-only 0abc 1def | while read x; do echo "'""$x""'"; done`

or try the same thing using sed, or

IFS='
' tar cjvf ~/deploy.tar.bz2 `git diff --name-only 0abc 1def`

Note that there is only a single newline in IFS.

However, if the name of your files contain newlines, you're doomed.

jpalecek
Doesn't work, I don't think that the quoting is evaluated the same way after being fed through the pipe.
Dana the Sane
Yes, sorry. I have edited the post to make it work, one solution with eval, another using the IFS variable.
jpalecek
+1  A: 

The hidden dot-files, are they dot-underscore-files?

If for file foo you have another ._foo, and you're on a Mac, the dot-underscore file is where the file resource fork / metadata is kept.

As for the git output, might try piping it through sed or perl for quoting. I believe xargs could help here too.

kch
Yes, I think you're right about the ._ files.
Dana the Sane
+1  A: 

I settled on the following solution with sed.

tar cjf ~/deploy.tar.bz2 \
`git diff --name-only 0abc 1def|sed -e "s/ /\\\ /g"`
Dana the Sane
A: 

Here's another, more elegant solution that works around escaping spaces in the filenames

git diff --name-only 0abc 1def | \
    tr '\n' '\0' | \
    xargs -0 tar -rjvf ~/deploy.tar.bz2

As jpalecek pointed out, one wold not want to run "tar -c..." multiple times, it's better to use -r.

hillu
I wouldn't do that. xargs doesn't give you any guarantee to run the command only once, so you could end up with tar running multiple times, and archive containing only files from the last batch.
jpalecek
Correct. It should, however, work just fine with -r.
hillu
+1  A: 

Why do not use --files-from=FILE or -T FILE option of tar, where FILE can be '-' to signify standard input?

 git diff --name-only 0abc 1def | tar -T - cjf ~/deploy.tar.bz2

You shouldn't have problem with spaces or tabs in filenames, or with single quotes, or backquotes, or backslashes (I think your solution would have problems with single quote "'" in filename). You might have problem with newlines in filenames, just like in IFS solution.

Jakub Narębski
+1. I bet this will "only" work with GNU tar :-)
hillu
I'll keep that in mind. If I run into more trouble, I'll probably just look at sanitizing names to alphanumeric strings.
Dana the Sane