Git 我如何看待与未跟踪、未分级、分阶段和提交的更改之间的差异?所有这些都是针对远程的更改?

Git 我如何看待与未跟踪、未分级、分阶段和提交的更改之间的差异?所有这些都是针对远程的更改?,git,Git,所以我有master,这是基线,我在开发人员的机器上有一个任意的情况,包括: 未跟踪的文件 未老化的变化 阶段性变化 本地提交 有没有一种方法可以将上述所有内容与远程内容进行比较?不是作为一个命令,而是只要您可以访问开发人员的机器,并且它可以访问其他存储库,就可以了。让我们调用开发人员的机器M,并假设在M上,通过origin访问“主”存储库,即开发人员最初运行git clone来创建现在在M上的存储库 第一步是确保M上的存储库与其他系统上的存储库是最新的。假设M$是机器M在克隆中时的提示:

所以我有
master
,这是基线,我在开发人员的机器上有一个任意的情况,包括:

  • 未跟踪的文件
  • 未老化的变化
  • 阶段性变化
  • 本地提交

有没有一种方法可以将上述所有内容与远程内容进行比较?

不是作为一个命令,而是只要您可以访问开发人员的机器,并且它可以访问其他存储库,就可以了。让我们调用开发人员的机器M,并假设在M上,通过
origin
访问“主”存储库,即开发人员最初运行
git clone
来创建现在在M上的存储库

第一步是确保M上的存储库与其他系统上的存储库是最新的。假设
M$
是机器M在克隆中时的提示:

M$ git fetch origin
M上的存储库现在有:

  • 其所有本地承诺
  • 索引中的暂存文件
  • 工作树中的未分级文件
  • 工作树中任何未跟踪的文件
  • 所有提交都可在
    origin
    上进行
现在M已经具备了生成您喜欢的任何差异所需的一切,问题变成了:您希望如何生成和呈现这些差异

让我们进一步假设我们对以下方面感兴趣:

  • 本地分支
    B
    上不在
    origin/B
    上的任何提交:

    ...--o--o--*--G--H   <-- B
                \
                 J--K--L   <-- origin/B
    
  • 分支
    B
    (提交
    H
    )的尖端与索引/暂存区域中的内容之间的差异。让我们再次假设
    HEAD
    names分支
    B
    ,以简化此操作:

    git diff --cached > /tmp/tip-to-staged
    
    这会将差异写入标准输出

  • 索引中的内容与工作树中的内容之间的差异:

    git diff > /tmp/staged-to-work-tree
    
    这会将差异写入标准输出

  • “nothing”(空树)和每个未跟踪文件之间的区别。这是从Git中最难获得的,从某种意义上说也是最愚蠢的,因为“无”和“某些文件集”之间的区别只是“某些文件集”。没有一个Git命令可以生成这个文件,但是您可以使用
    gitls文件--other
    来获取这些文件的列表,然后根据需要将它们打包。或者,您可以将它们写入commit;见下文

  • 不仅未跟踪而且被忽略的文件。(请注意,将被跟踪的文件列为“已忽略”对被跟踪的文件没有影响:这样的文件是被跟踪的,而不是被忽略的。“已忽略”是一种仅适用于已未跟踪的文件的状态。在任何情况下,“未跟踪”仅表示“不在索引中”。)这与前一点中的未跟踪文件相同:我们只是将它们分为“未跟踪且忽略”和“未跟踪且未忽略”。事实上,如果您选择使用
    gitls文件--other
    ,则会得到所有未跟踪的文件,包括被忽略的文件,除非添加
    --exclude standard
    选项

使用
git stash save
获取未跟踪或所有文件 请注意,我们必须使用至少三个Git命令:

git format-patch
git diff --cached
git diff
我们仍然没有未跟踪和/或忽略的文件。如果我们使用
git stash save
,我们可以得到最后一个。我们甚至可以删除一个(但只有一个)
git-diff
,同时添加至少一个
git-diff
。然而,其他事情变得更加复杂。特别是,
git stash save
如果没有任何内容可隐藏,则不会执行任何操作,我们必须检查以下内容:

M$ old_stash=$(git rev-parse -q --verify refs/stash)
M$ git stash save --untracked # assuming you do not want ignored files
M$ new_stash=$(git rev-parse -q --verify refs/stash)
M$ [ "$new_stash" != "$old_stash" ] && have_stash=true || have_stash=false
如果需要所有文件(未跟踪+忽略),请使用
--all
而不是
--untracked

我们还需要以下文件的哈希ID:

现在,我们可以从空树获取到包含未跟踪减去已忽略(
--未跟踪
)或未跟踪包括已忽略(
--所有
)文件的提交的差异:

现在可以安全地生成其他差异,或者您也可以在存储保存和可能弹出之前执行这些操作。(如果将上述内容转换为脚本,那么编写脚本的方式就不会那么笨拙了。)

如果你只想要一个差异
如果您对保存单个提交不感兴趣,您可以从上面原始图表中的commit
*
或commit
L
运行单个
git diff
。(如果
origin/branch
上没有新的提交,这些都是相同的提交。)当然,这不会显示索引(暂存)或工作树(未暂存)中的内容。与前面一样,您可以使用
git stash save
玩一些技巧,从索引和工作树以及(可选的)
--未跟踪的
--所有
文件进行提交。由于此操作的工作树提交在内部是合并提交,因此必须手动将其与感兴趣的父级区分开来。和以前一样,未跟踪的文件应该与空树进行区分。

这就是我发现的解决方案

git add --all -N :/
git --no-pager diff origin/master
只是“如果你想要一个单独的差异”案例的一个补充,如果你
git diff origin/master…
(是的,三个点),它有一个特殊的含义,它指出了
git merge base
,即
*
和与之相对的差异。
M$ empty_tree=$(git hash-object -t tree /dev/null)
M$ ($have_stash && git diff $empty_tree ${new_stash}^3) > /tmp/extra
M$ $have_stash && git stash pop
git add --all -N :/
git --no-pager diff origin/master