复制文件已更改或添加到新的孤立分支(git)

时间:2017-07-14 11:21:57

标签: git version-control

好的,git diff --name-status branch1..branch2给了我这个:

M       .gitignore
M       README.md
A       README_orig.md
M       deps/npm/lib/cache/add-remote-git.js
M       deps/npm/lib/fetch-package-metadata.js
M       deps/npm/lib/utils/git.js
A       git_wrapper.bat

我想 git diff 中的那些文件(不是branch2生成的补丁)复制全新的孤儿(空)分支并在那里提交。

是否有一些使用git或git checkout branch2 -- path1...path2等时间实现这一目标的方法?

更新

好的,我知道我应该解释一下背景。

这是一个相当不寻常的情况。我正在为公司打包一些精心设计的软件(即node.js,Visual Studio Code)。这需要对每个新版本的传入重现相同的自定义。

现在,例如Visual Studio代码编译的工作原理是它不提供编译应用程序所需的完整源代码。它在编译过程中下载了大量的东西(克隆几十甚至几百个Github repos),重新生成一些东西等,同时我们需要在下载的东西上应用我们的自定义和修复;一些节点模块的维护者没有响应,无法修复这些东西甚至应用我编写并尽职尽责地报告的修复,但是我们仍然需要应用这些修复,并且出于显而易见的原因,我们不想创建那些会在时间上变得过时的模块的分支。

我显然不能只使用通常的git diff来应用我们在v1.12.2acmev1.14.0asshippedbymicrosoft之间的特定修复和自定义,因为许多不相关的文件会发生变化。现在我想我只能将更改存储在过去的固定/自定义分支或产品标签中:

git diff commit_acme_fixed..commit_v1.14.0 -- file1.js
git diff commit_acme_fixed..commit_v1.14.0 -- file2.js

但......我真的不想这样做。我的想法是建立无关(孤立)acme_customisations分支,其中存储包含其版本的所有文件仅用于修补后续传入的新版本。然后,我可以在该分支中创建一个提交或标记,它将干净地封装我需要在传入的v1.14.0asshippedbymicrosoft版本上重播的更改,因为我们的自定义肯定会在基本产品发生变化的情况下迟早被修改。

对于其他人来说,更容易找出我们在基础产品版本之间更改的大量文件中改变了哪些文件(我想你可以通过提交者找到它,但是这是额外的过滤您需要做的级别以及您将错过某人作为提交者并且从视线中丢失一些更改的风险,而使用2个分支/标记/提交更自然且得到{支持的良好支持{1}})。

2 个答案:

答案 0 :(得分:0)

您的意思是您希望新提交中的那些文件吗?

我认为,在分支机构中考虑"文件是不明智的。 Git的分支太灵活了;你拥有的是提交,每个提交都有一些父提交和一个完整的快照,而不是补丁。但是在那里的孤儿分支状态中,没有当前的提交。当前分支只是一个名称和概念,而不是一个实际的分支。这也是您在新初始化的,完全空的存储库中的状态:当前分支只是一个名称master; master实际上还不存在。

当处于此状态时,git commit将照常创建提交,但此新提交将具有父提交 - 它是一个新的 root提交 - 只有这样,新分支才会存在,指向这个新的提交。运行git commit时索引中的文件是什么,这些文件将一如既往地在新提交中。因此,只需从索引中删除所有不需要的文件,并将所需的文件版本放入索引中。工作树的内容是无关紧要的,但在下面的步骤中,我们将让他们一起来骑。

git status  # make sure there's nothing to commit

(我们要破坏任何未保存的未经处理的工作文件大多是安全的,但明智的做法是不依赖它。)

现在我认为最简单的方法是继续设置以使用新的单根提交来创建新分支:

cd $(git rev-parse --show-toplevel)   # if not already there
git checkout --orphan newbr           # prepare to create new branch

现在清空索引:

git read-tree --reset -u $(git hash-object -t tree --stdin </dev/null)

这会计算the empty tree的哈希ID,并将其用作索引内容。相应的工作树文件被删除(-u),只留下未跟踪的文件(您可以根据需要删除或保留)。

然后,使用您建议的内容git checkout branch2 --,但使用差异化管理xargs进行自动化:

git diff --name-only -z branch1 branch2 | xargs -0 git checkout branch2 --

现在您已准备好提交...此新提交中的文件将由git checkout branch2 --添加到索引和工作树中。< / p>

(您可能希望将--diff-filter=AM添加到git diff,以便只获取AM个文件。此外,如果您反复自动执行此操作,考虑使用git diff-tree管道命令,而不是git diff,这是一个面向用户的瓷器命令可以根据用户设置更改其行为,因人而异或随着时间的推移而变化。)

答案 1 :(得分:0)

回购卷的数量和VSC完成所有这些都掩盖了这样一个事实:你在这里得到的是一个完全普通的git工作流程:你在供应商基础上维护acme分支。

你有一个acme分支与你的工作,你在新的供应商版本到货时重新调整,修复任何需要修复的东西,标记出版物提交,想要你的版本的人可以拉你的版本标签,可能在他们已经获得的供应商基础之上。

对于VSC已经克隆的任何一个回购,

git remote add acme u://r/l
git fetch acme v1.14acme
git checkout v1.14acme

你已经完成了。 fetch只是根据你的需要得到了不同之处,并且启动它显示了你正在发布的历史结构,而不仅仅是孤立的提示,无法自动将它绑定到特定的供应商基础。

编辑:真的,对于像这样的一次性提取,你可以省去添加遥控器:

git fetch u://r/l v1.14acme
git checkout v1.14acme