2

Problem

I have a git repo with two subdirectories under the root :/a and :/b, and I want to copy all versioned files from :/a into :/a-copy.

Essentially, I'd like to do

git mv a a-copy

without actually moving a.

More Details

There are also many non-versioned files in :/a, and I don't want to delete them, so I can't simply do

git clean -df a
cp -r a a-copy

The best workaround I've found (on Linux) is

mkdir a-copy
cd a
git ls-files -z | xargs -0 -i cp --parents {} ../a-copy

but I hope there is a simpler way.

Is This Question a Duplicate of "Do a “git export” (like “svn export”)?"?

That question is similar, but it only covers the case of copying/exporting the entire repo. I only want to copy part of the repo, i.e. the files under :/a, and not also the files under :/b. I read that question and its answers before posting this question. Now that I have an answer to my question, I see that the git archive based solutions to that other question also solve my problem here.

Community
  • 1
  • 1
ntc2
  • 11,203
  • 7
  • 53
  • 70
  • Why don't you just `clone` it again? Why does it matter if you then have to delete some of the result? What's the actual problem you're trying to solve here? – jonrsharpe Aug 17 '16 at 20:47
  • @jonrsharpe: I updated the question with more emphasis on the problem I'm trying to solve. If I simply use `cp -r`, then "deleting some of the result" is not easy, since I have to manually delete the unversioned files (there are many). Yes, `git clone` following by `cp -r` will work, but that seems like another overly complicated work around. I would expect there to be a simple, built in way to do this, similar to `git archive` or `git checkout-index`. – ntc2 Aug 17 '16 at 21:02
  • *"I want to copy all versioned files from `:/a` into `:/a-copy`"* - ...why? – jonrsharpe Aug 17 '16 at 21:13
  • @jonrsharpe: because I'm forking the development under `:/a`. – ntc2 Aug 17 '16 at 23:03
  • Nor sure quite what you mean by that. Why not make it a submodule, it it will have a separate lifecycle? – jonrsharpe Aug 18 '16 at 06:16
  • *if. Or make it a dependency and separate it entirely. This could be an [XY problem](http://meta.stackexchange.com/q/66377/248731). – jonrsharpe Aug 18 '16 at 08:04
  • Possible duplicate of [Do a "git export" (like "svn export")?](http://stackoverflow.com/questions/160608/do-a-git-export-like-svn-export) – jonrsharpe Aug 18 '16 at 11:43
  • @jonrsharpe: I don't think it's an XY problem. Let me try to be more concrete. Here `:/a` is something like `:/test/a` and I'm creating a new test `:/test/similar-to-a` which is similar to `:/test/a`. The two tests are similar enough that I want to copy `:/test/a` to get started, but creating an abstraction `:/test/generic-a` from which `:/test/a` and `:/test/simlar-to-a` are derived would be unnecessary abstraction / over engineering. – ntc2 Aug 18 '16 at 18:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/121285/discussion-between-ntc2-and-jonrsharpe). – ntc2 Aug 18 '16 at 18:37

1 Answers1

4

The command sequence you are looking for is:

git archive HEAD a | tar -x -C /tmp
mv /tmp/a b

or equivalently

cd a
git archive --prefix=b/ HEAD . | tar -x -C ..

git archive creates a tar archive using that contains the files from the a subdirectory. It uses the versions of these files from the HEAD revision; you can specify an other Git revision if you prefer.

The archive is written to stdout and it goes through the pipe (|) to the tar program that extracts the files (-x) and puts them into the directory /tmp (-C).

Because Git adds the files together with their enclosing directory (a), tar creates the directory a into /tmp and it contains the files you want.

You use mv to move (and rename) /tmp/a and place it where you need it.

ntc2
  • 11,203
  • 7
  • 53
  • 70
axiac
  • 68,258
  • 9
  • 99
  • 134
  • Thanks! That is definitely simpler, and allows me to only get the committed versions (at any revision) without having to `git stash` or `git checkout` first. – ntc2 Aug 17 '16 at 21:08