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

时间:2018-08-30 11:17:04

标签: git branch git-diff

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

大师

 |_ 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 分支,以使其具有主控的所有源文件状态,并且除去virus.exe文件。

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

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

但是我也想摆脱 master 的工作集中不存在的文件。在此示例中,这将是文件virus.exe。仅创建主组件的新 development 分支是不可行的,因为将 development 分支保留为 orphan 很重要。当通过/关闭 master 分支覆盖/分支 development 分支时,它将丢失 orphan 状态,因为它将适应的整个历史记录>大师

有人知道一种方法:

  • 获取文件中两个分支之间的区别? 不是他们的提交差异
  • 通过最终提交删除所有发现的文件差异(以保持历史记录完整吗?)

编辑: 我找到了使文件有所不同的命令:

$ 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

1 个答案:

答案 0 :(得分:1)

分支没有工作集。 (嗯,也许他们会这么做,因为您尚未定义工作集,但是Git也没有定义工作集。但是由于我不知道您的意思,所以我正在使用 working设置作为工作树的别名,定义明确的分支,分支没有工作树。)

分支名称的作用是选择一个特定的提交。然后,该提交有一些父提交(如果是合并,则有多个提交);父级有自己的父级,依此类推,形成了一个提交链。结果,我们可以说分支(或分支名称)包含了一组提交::这些是可以从名称中到达的提交。有关所有这些的良好介绍,请参见Think Like (a) Git

每个提交都有一个存储的 tree 或快照。如您所见,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 。例如,较短的序列可能是将A重命名为B,然后删除第17行,显然比删除文件A短得多,然后用以下10,000行创建文件B:[非常长行列表]

面向用户的前端git diff命令实际上运行git diff-treegit diff-index或其他任何命令,但使用用户的配置(diff.renames和{{1}例如}),并通过 pager 发送输出,进行着色等等。 Git称这些命令为 porcelain (瓷器),因为它们应该是用户友好的(相对于管道,隐藏在墙后,看不见)。

提交 new 提交时,Git会存储一个新的快照。当您运行diff.renameLimit时,Git会根据其 index 中Git的内容构建新快照。新提交的 parent 是当前分支的旧提示。新的提交成为当前分支的尖端。这就是分支的增长方式。

您使用的各种命令(例如git commitgit rm)在 index 上运行。您使用git add将分支的尖端提交提取到该索引中。索引中 中存储的文件很难看-使用git checkout branch可以获得完整的列表,但这很少有用。无论如何,这些文件在索引中并最终(最终)被冻结为提交,因此它们都是特殊的仅Git形式。因此,要使用这些文件,当您使用Git提取提示提交时,还需要使用Git将所有文件都提取到工作树中。

工作树具有那些普通格式的文件,您和您的计算机可以在其中以普通方式使用它们。但是您在此工作树中所做的所有操作实际上都是针对索引的,因为索引包含了 next 提交中的内容。运行git ls-files --stage会将索引内容打包(冻结)为快照,并将其添加为分支的新技巧。

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