如何获得两个 git 分支的工作集(不是提交)之间的差异

How to get the difference between the working sets (not commits) of two git branches

我有以下两个文件不同的分支

大师

 |_ document.txt
 |_ document_two.txt
 |_ document_three.txt

发展

 |_ document.txt
 |_ document_two.txt
 |_ document_three.txt
 |_ virus.exe // want to get rid of that

这些是 git log 两者的结果(从上到下

大师

commit: fdsdfsf1342re5252423425242234 (master, development)
add document one

commit: 563523523g233g5232sdfawe22434 (master, development)
add document two

commit: 56652u747241523g52352fsdfawew (master, development)
add document three

发展

commit: fdsdfsf1342re5252423425242234 (master, development)
add document one

commit: 563523523g233g5232sdfawe22434 (master, development)
add document two

commit: 1213421g233g5232s41dfawe22434 (development)
ADD VIRUS.EXE ! XXX

commit: 5423345652u7433g52352fsdf1223 (development)
change document three completly

commit: 56652u747241523g52352fsdfawew (master, development)
add document three

目标

我想清理 development 分支,以便它具有 master 的所有源文件状态 virus.exe文件已删除。

我已经找到了让 master 状态覆盖 development 文件状态的方法。

阅读此处Make the current Git branch a master branch

但我也想删除 master 工作集中不存在的文件。在此示例中,这将是文件 virus.exe。仅仅创建一个新的 development master 分支不是一种选择,因为将 development 分支作为 orphan 很重要。当 overwriting/branching development 分支 by/off master 分支时它将失去 orphan 状态,因为它将适应 master

的整个历史

有没有人知道如何:

编辑: 我找到了给我文件差异的命令:

$ git diff-tree -r --name-status --diff-filter=A master..development
A       virus.exe

有没有一种优雅的方式可以直接使用输出从开发分支中删除?我会在以下方面使用它:

git checkout development && git rm virus.exe && git commit -m "clean development" && git push origin

分支没有工作集。 (好吧,也许他们这样做了,因为你没有定义 working set,但是 Git 也没有定义 working set。但是因为我不知道你的意思,我我使用 working set 作为 work-tree 的别名,is 定义明确,并且分支没有工作树。)

分支名称所做的是 select 一个特定的提交。该提交然后有一些父提交(如果是合并,则有多个父提交);父级有自己的父级,依此类推,形成一个提交链。因此,我们可以说一个分支(或分支名称)包含 一些提交集:这些是 可从 名称访问的提交.有关所有这些的详细介绍,请参阅 Think Like (a) Git

每个提交都有一个存储的 或快照。正如您所发现的,git diff-tree 是所谓的 plumbing 命令(可编写脚本的主力),用于比较在两次提交中发现的两棵树:

git diff-tree -r commit1 commit2

比较整个树,递归地(-r),比较两个快照中包含的所有文件。你可以这样拼写commit1..commit2:完全一样的意思,比较时左边用commit1,右边用commit2。此比较的输出本质上是一系列指令,例如,向该文件添加一些行,从该文件中删除一些行,然后您将导致附加到 commit1 的树与附加到 commit2.

的树

您可以添加 --name-only--name-status 等选项,以及 --find-renames 和可选的 相似性指数 值(百分比) Git 计算重命名然后更改文件的位置比更简单的 删除文件 A 并使用这些内容从头创建新文件 B 产生更短的指令序列。例如,可能更短的序列是 rename A to B, then remove line 17, 这显然比 remove file A, then create file B with these 10,000行:[非常长的行列表].

前端,面向用户的git diff命令有效运行s git diff-treegit diff-index或其他,但有用户的配置(diff.renamesdiff.renameLimit ),并通过 pager 发送输出,着色等。 Git 调用这些命令 porcelain 因为它们应该是用户友好的(相对于管道,隐藏在墙后,看不见)。

当您进行 new 提交时,您会 Git 存储一个新的快照。 Git 根据您 运行 git commit 时 Git 在其 索引 中的任何内容构建新快照。新commit的parent是当前分支的old tip;新提交 成为 当前分支的顶端。树枝是这样生长的。

您使用的各种命令,例如git rmgit add,对索引 进行操作。您使用 git checkout <em>branch</em> 将分支的尖端提交提取到此索引中。存储在 索引的文件很难看到——您可以使用 git ls-files --stage 获得完整列表,但这很少有用。这些文件在索引中并(最终)冻结到提交中,无论如何都是特殊的 Git-only 形式。因此,要 使用 这些文件,当您 Git 提取提示提交时,您还 Git 将所有文件提取到 工作-树.

工作树以普通格式包含这些文件,您和您的计算机可以在其中以普通方式使用它们。但是你在这个工作树中所做的一切实际上都是为了与索引混淆,因为它是包含 next 提交中的内容的索引。 运行 git commit 将索引内容打包(冻结)到快照中,并将其添加为分支的新提示。

因此,如果您比较两个提交(使用 git diffgit diff-tree),然后对您的索引进行一些更改并进行新的提交,您所做的就是更改索引并使用它进行新的提交。两个提交的比较由您决定。请注意,您还可以使用 git diff --cached(瓷器)或 git diff-index --cached(管道)将任何一个提交 进行比较。而且,您还可以使用这些命令比较索引与工作树,或提交与工作树。