在 BASH 如何递归地只复制由 Git 控制版本的内容?
In BASH How Can One Recursively Copy Only Content Version-Controlled by Git?
有没有办法在 bash 终端批量递归复制(cp -rf
等效)从一个子目录到另一个子目录,保留目录结构但仅复制 files/directories 是版本控制的通过 git
?
天真的策略是...
cp -rf <targetDir> variantDir/; git add variantDir;
...但这会拾取一堆文件,这些文件是 IDE 删除的数据文件,等等。我正在处理的文件目前在 [= 中不受版本控制17=].
作为背景,我有以下目录结构:
${baseDir}/
${baseDir}/variantA
基本上,${baseDir}/
包含所有原始版本控制的内容,${baseDir}/variantA
包含针对目标变体的不同内容。对于原始目标文件夹 ${baseDir}/variantA
将被忽略。对于第二个目标,文件夹 variantA
被包含在内,有效地取代了除路径的 variantA
部分以外的任何匹配内容。
即如果我有:
${baseDir}/someFolder/someStuff.cpp
${baseDir}/variantA/someFolder/someStuff.cpp
它将为第二个目标使用第二条路径,为第一个目标使用第一条路径。
现在我要添加 variantB
,它是一个完整的变体(不像 variantA
有一些落入基本目标的文件)。它更接近 variantA
所以我想先复制基本文件夹中的所有内容,然后将 variantA
子文件夹中的所有内容复制到 variantB
子文件夹中......这样我就有了一个新的将所有内容(包括失败内容)复制到版本提交,并优先选择 variantA
文件版本,当存在此类重叠时。
我会使用上面的天真片段,但我有一个更根本的问题,我的 IDE 已经丢弃 *.xml
文件和其他垃圾 git
在某种程度上足够聪明来标记因为不是未提交的内容(可能是特定于语言的),但 cp
会忽略。我相信 git
会在明确要求的情况下复制这些文件,因此,我想排除所有非 git
控制的内容,同时使用之前所述的一般策略。
仅将源代码管理下的文件从变体 A 复制到变体 B:
cd variantA
rsync --files-from <(git ls-files .) . ../variantB
这通过仅包含由 git ls-files
返回的文件来实现。
编辑:<()
语法称为 process substitution。
如果你有 GNU cp
,你可以使用 --parents
选项:
mkdir variantB
cd variantA
cp --parents $(git ls-files .) ../variantB
git ls-files | tar Tc - | tar Cx /path/to/destination
这会获取您在工作树中当前位置的内容。要使用提交的子目录,请使用 git archive
解决方案 、
git archive master:path/to/subdir | tar Cx /path/to/destination
要处理您当前添加但未提交的内容,您可以将 $(git write-tree)
替换为上面的 master
。
为什么不创建一个新的工作树(显然其中只有源代码控制的文件,因为它是从源代码管理生成的)?
有几种方法可以做到这一点(使用克隆或工作树),但我认为
git worktree add -b variantB path/where/variantB/will/be/created master
会让您开始使用相关文件(受源代码控制的文件)。然后你只需将 path/where/variant/B/will/be/created/variantA
复制到 path/where/variant/B/will/be/created
并且由于 -b
选项,您已经在一个新的分支上 - 这就是您可能希望保留此变体的方式,因为它是一个完整的替代品。 (对于 varientA,这是值得商榷的,因为您希望 variantA 与它不变的文件的基线更改保持同步...)
但是如果你不想为此维护一个新的分支,没什么大不了的。使用克隆或工作树添加命令(不带 -b
)创建上述 variantB 的工作树图像,然后将生成的文件移动到 .../variantB 目录下的默认工作树中
有没有办法在 bash 终端批量递归复制(cp -rf
等效)从一个子目录到另一个子目录,保留目录结构但仅复制 files/directories 是版本控制的通过 git
?
天真的策略是...
cp -rf <targetDir> variantDir/; git add variantDir;
...但这会拾取一堆文件,这些文件是 IDE 删除的数据文件,等等。我正在处理的文件目前在 [= 中不受版本控制17=].
作为背景,我有以下目录结构:
${baseDir}/
${baseDir}/variantA
基本上,${baseDir}/
包含所有原始版本控制的内容,${baseDir}/variantA
包含针对目标变体的不同内容。对于原始目标文件夹 ${baseDir}/variantA
将被忽略。对于第二个目标,文件夹 variantA
被包含在内,有效地取代了除路径的 variantA
部分以外的任何匹配内容。
即如果我有:
${baseDir}/someFolder/someStuff.cpp
${baseDir}/variantA/someFolder/someStuff.cpp
它将为第二个目标使用第二条路径,为第一个目标使用第一条路径。
现在我要添加 variantB
,它是一个完整的变体(不像 variantA
有一些落入基本目标的文件)。它更接近 variantA
所以我想先复制基本文件夹中的所有内容,然后将 variantA
子文件夹中的所有内容复制到 variantB
子文件夹中......这样我就有了一个新的将所有内容(包括失败内容)复制到版本提交,并优先选择 variantA
文件版本,当存在此类重叠时。
我会使用上面的天真片段,但我有一个更根本的问题,我的 IDE 已经丢弃 *.xml
文件和其他垃圾 git
在某种程度上足够聪明来标记因为不是未提交的内容(可能是特定于语言的),但 cp
会忽略。我相信 git
会在明确要求的情况下复制这些文件,因此,我想排除所有非 git
控制的内容,同时使用之前所述的一般策略。
仅将源代码管理下的文件从变体 A 复制到变体 B:
cd variantA
rsync --files-from <(git ls-files .) . ../variantB
这通过仅包含由 git ls-files
返回的文件来实现。
编辑:<()
语法称为 process substitution。
如果你有 GNU cp
,你可以使用 --parents
选项:
mkdir variantB
cd variantA
cp --parents $(git ls-files .) ../variantB
git ls-files | tar Tc - | tar Cx /path/to/destination
这会获取您在工作树中当前位置的内容。要使用提交的子目录,请使用 git archive
解决方案
git archive master:path/to/subdir | tar Cx /path/to/destination
要处理您当前添加但未提交的内容,您可以将 $(git write-tree)
替换为上面的 master
。
为什么不创建一个新的工作树(显然其中只有源代码控制的文件,因为它是从源代码管理生成的)?
有几种方法可以做到这一点(使用克隆或工作树),但我认为
git worktree add -b variantB path/where/variantB/will/be/created master
会让您开始使用相关文件(受源代码控制的文件)。然后你只需将 path/where/variant/B/will/be/created/variantA
复制到 path/where/variant/B/will/be/created
并且由于 -b
选项,您已经在一个新的分支上 - 这就是您可能希望保留此变体的方式,因为它是一个完整的替代品。 (对于 varientA,这是值得商榷的,因为您希望 variantA 与它不变的文件的基线更改保持同步...)
但是如果你不想为此维护一个新的分支,没什么大不了的。使用克隆或工作树添加命令(不带 -b
)创建上述 variantB 的工作树图像,然后将生成的文件移动到 .../variantB 目录下的默认工作树中