Reputation: 14532
I have a project, where I want to separate the (not versioned / .gitignore
d) files (the most of them are config files) from the actual source code. I want to copy them to a directories structure identical to the project's directories structure. E.g.:
/foo
/bar/config/env.xml <-- ignored
/bar/config/env.xml.dist
/buz/keys <-- ignored
/buz/logs <-- ignored
/buz/source
$ git extract-ignored-files --exclude-from-extracting=/buz/logs (pseudocode)
Aimed result:
/bar/config/env.xml <-- ignored
/buz/keys <-- ignored
The concrete requirement behind it is to be able to transfer settings from one system to another (and set up this another one quickly by adapting only a couple of settings).
How to export the .gitignore
d files? In the best case I also would like (1) to keep there by the folders' structure identical to the original structure and (2) be able to exclude some paths from the extracting result.
Upvotes: 1
Views: 59
Reputation: 14532
1. Define the paths, you want to transfer. It will be a subset of the set of the ignored files.
This can be done various ways, e.g. by reviewing the .gitignore
and transforming its rules to paths or by using git status --ignored
or git check-ignore *
. I prefer this way:
a. Get all .gitignore
d files (git ls-files --others > ./transfer-excludes.txt
) (in my case I got a file with about 22k
lines).
b. Define from the result file's entries manually the patterns you don't (!) want to transfer. It can be for example your IDE settings, the folder with the external libraries, logs etc. -- everything you definitely won't need to copy to another project instance.
2. Get the paths to be transferred.
$ git ls-files --others --exclude-from=./transfer-excludes.txt > ./transfer-files.txt
The approach might need some more effort. But then all possible ignore paths (including the ones excluded by the sub-directories' .gitignore
s) become visible and can be checked.
3. Copy the files.
It's just a simple bash script, that scans the paths, creates the needed directories structure (by using mkdir -p
), and copies the files:
#!/bin/bash
INFILE="./transfer-files.txt"
TARGETROOT="./transfer"
while read line
do
TARGETDIR=`dirname $line`
TARGETPATH="${TARGETROOT}/${TARGETDIR}"
if [ ! -d "${TARGETPATH}" ]
then
mkdir -p "${TARGETPATH}"
fi
# echo ${TARGETPATH}
cp "$line" "${TARGETPATH}"
done < ${INFILE}
The cp --parents
instead of the combination of mkdir -p
and cp
doesn't work in this case, since it cannot crate complete path recursively, if it's not there yet.
$ ./transfer.sh
That's it.
A little check:
$ find ./transfer/ -type f -exec du -a {} +
The output should equal to the list of the files from the transfer-files.txt
.
Possible improvements:
2
and 3
can be merged to script. (But sometimes you won't want to, in order to have a chance to check the file list first.).gigitnore
file -- in this case the transfer-excludes.txt
should be updated.Upvotes: 0
Reputation: 94676
rsync -R
preserves relative path names:
rsync -aR `git ls-files --others` ignored_files/
Upvotes: 1
Reputation: 5598
The --parents
flag to cp will maintain directory structure.
mkdir ignored_files
for x in `git status --ignored .`; do
cp -va --parents $x ignored_files/$x
done
Upvotes: 1