git-log 缺少撤消更改的合并提交

2023-11-29

考虑这个测试脚本。

#!/bin/sh -x

#initialize repository
rm -rf missing-merge-log
mkdir missing-merge-log
cd missing-merge-log
git init

# create files, x, y, and z
echo x > x
echo y > y
echo z > z
git add -A .
git commit -m "initial commit"

# create a branch
git branch branch

# change x and z on master
echo x2 > x
echo z2 > z
git commit -am "changed x to x2, z to z2"
git log master -- x

# change y and z on the branch
git checkout branch
echo y2 > y
echo z3 > z
git commit -am "changed y to y2, z to z3"

# merge master into branch
git merge master
# resolve z conflict
echo z23 > z
git add z
# undo changes to x during merge conflict resolution
# (imagine this was developer error)
git checkout branch -- x
git commit --no-edit

# merge branch into master
git checkout master
git merge branch

# now the x2 commit is entirely missing from the log
git log master -- x

我们首先创建三个文件,x, y, and z,并创建一个名为branch. In master,我们承诺更改x and z,并在分支中,我们提交更改y and z.

然后,在分支中,我们合并master,但在合并冲突解决期间,我们将更改恢复为x。 (对于这个例子,假设这是一个开发人员错误;开发人员并不打算拒绝对x.)

最后,回到master,我们合并分支中的更改。

我希望此时git log x显示三个更改:初始提交、更改x在 master 上,以及将更改恢复到的分支提交x.

但相反,在剧本的最后,git log仅显示对 x 的初始提交,没有表明x曾经被修改过!这使用 git 版本 2.22.0。

Why is git log做这个?有没有参数git log -- x那会显示这里发生了什么?git log --all -- x没有帮助。

(git log --all确实显示了所有内容,但在现实生活中,这会显示对所有文件的所有更改,包括与y and z,这太困难了。)


TL;DR

Use --full-history-但您可能还想要更多选择,所以请继续阅读。

Long

首先,非常感谢您的复制脚本!这在这里非常有用。

Next:

(git log --all确实显示了所有内容,但在现实生活中,这会显示对所有文件的所有更改,包括与y and z,这太困难了。)

是的。但它表明任何一个都没有问题commits;问题完全在于git log正在制作,在这里。这与可怕的事情有关历史简化模式,其中:

git log master -- x

invokes.

git log没有历史简化

让我添加以下输出:

git log --all --decorate --oneline --graph

(“在一条狗的帮助下进行 git log”),因为我使用脚本进行了复制,所以它的哈希 ID 与您(或执行另一个复制的任何其他人)所具有的哈希 ID 不同,但具有相同的结构,因此让我们讨论提交:

*   cc7285d (HEAD -> master, branch) Merge branch 'master' into branch
|\  
| * ad686b0 changed x to x2, z to z2
* | dcaa916 changed y to y2, z to z3
|/  
* a222cef initial commit

现在,一个正常的git log, 没有-- x检查文件x, does not打开历史简化。 Git 从您指定的提交开始 - 例如:

git log dcaa916

开始于dcaa916—or at HEAD如果您没有指定任何内容。

那么,在这种情况下,git log从提交开始cc7285d。 Git 显示该提交,然后移至该提交的父级。这里有两个父母——dcaa916 and ad686b0——所以 Git 放置both致力于优先队列。然后它从队列的头部拉出其中一个提交。当我尝试这个时,它拉出的是dcaa916。 (在更实际的图表中,默认情况下它将使用具有较晚提交者时间戳的时间戳,但是使用脚本构建此存储库后,两次提交都具有相同的时间戳。)Git 显示提交并放置dcaa916的父母a222cef进入队列。为了拓扑的完整性,给定这个特定的图,队列前面的提交现在总是ad686b0,所以 Git 显示该提交,然后......

好吧,现在,父母ad686b0 is a222cef, but a222cef已经在队列中了!这就是“为了拓扑理智”的意义所在。通过不显示a222cef太早了,我们要确保我们不会意外地表现出来a222cef两次(以及其他问题)。现在队列有a222cef就在其中,没有别的东西,所以git log takes a222cef离开队列,显示a222cef,并把a222cef的父母在队列中。在这个重现器示例中,没有父级,因此队列保持为空,并且git log可以完成,这正是我们在常规中看到的git log。在一只狗的帮助下,我们也得到了图表,以及单行输出变体。

git log历史简化

git 没有file历史。存储库中的历史记录包括commits. But git log将尽最大努力show文件历史记录。要做到这一点,它必须合成一个,并且做到that,Git 的作者选择简单地省略一些提交子集。该文档试图用一句话段落来解释这一点:

有时您只对历史记录的一部分感兴趣,例如修改特定 的提交。但有两个部分历史简化,一方面是选择提交,另一方面是如何做到这一点,因为有多种策略可以简化历史记录。

我认为这一段解释是行不通的,但我还没有想出我认为的right解释,也可以。 :-) 他们在这里试图表达的是:

  • Git 不会告诉你all提交。它将显示一些选定的提交子集。

    这部分很有道理。我们已经看到,即使没有历史简化:Git 也以lastcommit,我们用分支名称或用HEAD或者其他什么,然后向后工作,一次一个提交,如果需要的话,一次将多个提交放入其优先级队列中。

    With历史简化,我们仍然使用优先级队列遍历提交图,但对于许多提交,我们只是不显示提交。到目前为止还不错,但现在 Git 做出了一些改变,导致他们写出了那个奇怪的段落。

  • 如果 Git 不打算向您显示所有提交,也许它可以cheat甚至懒得follow一些叉子。

    这是最难表达的部分。当我们从分支尖端向后工作到提交图根时,每个merge提交(两个提交流合并在一起)成为一个分叉(其中两个提交流分开)。特别是,承诺cc7285d是一个合并,当我们don't当发生历史简化时,Git 总是将父级都放入队列中。但当我们do有时会发生历史简化,Gitdoesn't将这些提交放入队列中。

这里真正棘手的部分是决定which提交进入队列,这就是文档的“更详细的解释”和TREESAME我鼓励人们通读它,因为它有很多好的信息,但内容非常密集,而且不太擅长defining首先,TREESAME。文档是这样说的:

假设您指定foo作为。我们将调用修改的提交foo!TREESAME,其余的都是TREESAME。 (在差异过滤中foo,它们看起来分别不同和相等。)

这个定义depends关于提交是非合并提交!

所有提交都是快照(或更准确地说,contain快照)。所以没有提交,单独采取,修改any文件。它只是has该文件,或者没有该文件。如果有该文件,则它有一些特定的内容for文件。要将提交视为更改(作为一组修改),我们需要选择一些other提交、提取both提交,然后比较两者。对于非合并提交,有一个明显的提交可供使用:父级。给定一些提交链:

...--F--G--H--...

我们来看看是什么changed提交中H通过提取两者G and H,并对它们进行比较。我们来看看是什么changed in G通过提取F and G,并对它们进行比较。这就是 TREESAME 段落的内容:我们采取F and G,比如说,然后删除除您询问的文件之外的所有文件。然后我们比较剩余的文件。它们在精简版中是否相同F and G?如果是这样,F and G是树一样的。如果没有,他们就不是。

但根据定义,合并提交至少有two父母:

...--K
      \
       M
      /
...--L

如果我们正在合并提交M,我们选择哪一个父级来确定什么是 TREESAME,什么不是?

Git 的答案是比较提交all父母的,一次一个。一些比较可能会导致“is TREESAME”,而其他比较可能会导致“is not TREESAME”。例如,文件foo in M可能匹配文件foo in K和/或文件foo in L.

Git 使用哪些提交取决于您提供的附加选项git log:

默认模式

如果提交对于任何父级都不是 TREESAME(尽管可以更改,请参阅--sparse以下)。如果提交是合并,并且对于一个父级来说是 TREESAME,则仅遵循该父级。 (即使有多个 TREESAME 父项,也只关注其中之一。)否则,请关注所有父项。

所以让我们考虑合并cc7285d,并将其与其(两个)父母中的每一个进行比较:

$ git diff --name-status cc7285d^1 cc7285d
M       z
$ git diff --name-status cc7285d^2 cc7285d
M       x
M       y
M       z

这意味着git log只会步行first父母,承诺cc7285d^1(这是dcaa916)——这就是doesn't change x:

...如果提交是合并,并且对于一个父级来说是 TREESAME,则仅遵循该父级。 ...

So this git log步行提交cc7285d,然后提交dcaa916,然后提交a222cef,然后停止。它从不考虑提交cc7285d^2(这是ad686b0)根本。

本节的其余部分git log文档描述了选项--full-history, --dense, --sparse, and --simplify-merges(甚至我也不明白最后一个选项的真正目的:-))。在所有这些中,--full-history是最明显的并且会做你想做的事。 (--ancestry-path and --simplify-by-decoration也是这一部分,但它们不影响合并时的路径。)

Caveats

While --full-history将确保 Git 遍历每个合并的所有“腿”,git log -p本身默认显示no合并提交的差异。您必须添加三个选项之一 --c, --cc, or -m— 使git log -p显示任何合并的任何差异。

如果您的目标是专门寻找bad双父合并,一种删除本应保留的某些特定更改的合并,您可能希望向其两个父项中的至少一个(也许是两个)显示该合并的差异。这git show命令将执行此操作,但其默认值是--cc风格。这git log命令根本不会这样做。如果你添加--cc给你的git log,你会得到相同的差异git show默认情况下会显示——但这也行不通。

The --cc or -coptions 告诉 Git,当查看合并提交时,Git 应该将提交与所有父项进行比较,然后生成一个summarydiff,而不是详细的。摘要的内容不包括与一个或所有父项匹配的部分。您正在寻找一个意外地删除了重要更改的合并,该合并是same至少作为其父母之一,当它应该是不同的来自那位家长。这个组合的差异将是hide没有但应该改变的地方。那么你don't want -c or --cc.

这就留下了-m选项。什么时候git show or git log将显示差异,并且提交是合并提交,Git 会显示每个父项有一个差异。也就是说,对于像这样的合并提交M, git show -m首先会比较K vs M并显示差异。然后就会比较L vs M并显示其他差异。That's对于这种特殊情况,您在这里需要的选项。

注意-m很好地结合--first-parent仅显示与每个合并的第一个父级的完整差异。很多时候就是这样exactly你想要什么。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

git-log 缺少撤消更改的合并提交 的相关文章

  • git stash 删除最旧的存储(比如最旧的 5 个存储)

    如何在一个语句中删除最旧的存储 例如最旧的 5 个存储 而不是执行以下操作 git stash drop stash 3 git stash drop stash 4 git stash drop stash 5 git stash dro
  • 从 github 中删除子项目提交

    我有两个存储库A and B 我错误地在我的机器上将仓库 B 克隆到了 A 内 我从存储库 B 中删除了所有代码 但是当我在源上从 A 推送并合并代码时 它还显示了子项目提交B在 Github 仓库上 我想从我的 master 上删除子项目
  • 如何升级 Windows 中 git svn 使用的 SVN 版本?

    我的公司正在将SVN升级到1 7 检查git svn version显示正在使用的SVN版本是1 4 6 我想获得 git svn 使用的 SVN 版本接近 1 7 但是 我没有看到有关更新 git svn 使用的 SVN 版本 在 Win
  • 致命:不是 git 存储库(或任何父目录):.git [重复]

    这个问题在这里已经有答案了 当我尝试推送 github com 上的现有存储库时 当我输入命令时 网站提示我将其输入终端 我收到了以下致命错误消息 Not a git repository or any of the parent dire
  • Git post-receive - 如何检查推送的分支是否与主分支合并

    在我们的团队中 我们通常将所有任务推送到单独的分支中 然后发布经理审查这些分支并将它们合并到 主 分支中 有时团队成员忘记将他们的分支与主分支合并 在推送之前 所以我想做的是 在用户推送后输出一条消息 请与主分支合并 我想我需要检查一些内容
  • git 如何查找分支源自的提交哈希

    假设我从主分支分支到主题分支 然后在主题分支上进行了一些提交 是否有命令告诉我主题分支源自的主分支上的提交哈希 理想情况下 我不必知道我做了多少次提交 试图避免 HEAD 5 我已经用谷歌搜索过 但似乎无法找到答案 谢谢 use git m
  • 如何让 Gitlab 运行程序在成功构建时将代码合并到分支中

    嗯 标题几乎是不言自明的 总之 如果构建成功 我希望将一个分支 即开发 合并到另一个分支 即生产 我尝试了 jakub kania 解决方案 但我总是得到id rsa invalid format 我认为 gitlab 秘密变量以某种方式被
  • Jenkins GIT 包含从未构建过的区域

    我正在尝试使用包含区域在 Jenkins 中构建我的工作 但每当选中此选项时 民意调查结果总是说未检测到任何更改 我尝试了许多不同的路径 以及使用工作区进行 不进行强制轮询 结果是轮询从未检测到任何更改 但一旦我删除这些选项 它们就会在下一
  • SSL 适用于浏览器、wget 和curl,但不适用于 git

    我有一个网站 用于托管 redmine 和几个 git 存储库 这非常适合 http 但我无法使用 https 进行克隆 即 git clone http mysite com git test git 工作正常 但是 git clone
  • GitHub Pages (github.io) doxygen 生成的页面未找到 (404)

    我不明白为什么找不到 doxygen 生成的页面 404 它在Github存储库中的路径是https github com AubinMahe AubinMahe github io blob master doxygen html dd
  • Spring Cloud Config - 不允许使用 git-upload-pack

    我有一个在 docker 环境中运行的 spring boot 应用程序 它连接到 Git 存储库以获取应用程序的配置 我的问题是 当尝试获取 properties 文件时 应用程序有时会出错 这很奇怪 因为如果我更改用户和密码 同一个应用
  • http.h:6:23: 致命错误:curl/curl.h:没有该文件/目录

    我在 CentOS 7 中下载 git 包 wget https www kernel org pub software scm git git 2 0 1 tar gz tar xzf git 2 0 1 tar gz 当我编译git时
  • 如何让 git 显示作者日期指定日期范围内的提交?

    显然this https stackoverflow com a 11189286 281545 git log all after
  • 检查 Git 中是否需要 pull

    如何检查远程存储库是否已更改并且需要拉取 现在我使用这个简单的脚本 git pull dry run grep q v Already up to date changed 1 但它比较重 有没有更好的办法 理想的解决方案是检查所有远程分支
  • 如何在源代码管理中存储 Visual Studio 的调试配置

    Visual Studio 的调试配置存储在 user文件是用户特定的并且传统上被源代码管理忽略 我对工作目录参数感兴趣 我需要它在程序员的机器上保持一致 并且它具有以下价值 outDir而不是默认的 ProjectDir 我怎样才能解决这
  • git am 和 git apply 有什么区别?

    Both git am https git scm com docs git am and git apply https git scm com docs git apply可用于应用补丁 看起来git am自动提交 而git apply
  • Git撤销本地分支删除

    我刚刚删除了错误的分支 并进行了一些我需要的实验性更改git branch D branchName 如何恢复分支 您可以使用git reflog http git scm com docs git reflog查找分支最后一次提交的 SH
  • 为什么 git 在每次合并时都运行“git gc --auto”?

    今天 git 开始表现得很有趣 嗯 比平时更有趣 坚持运行git gc每次合并后 即使它们是背靠背的 C Projects my current project gt git pull remote Counting objects 31
  • 如何在现有裸存储库中创建引用日志信息

    您可能已经知道 默认情况下 git 不会为新的裸存储库启用引用日志更新 问题是 我有一个很长的历史存储库 但它是在我设置 logAllRefUpdates 标志之前创建的 现在我希望其他应用程序可以使用该信息 如何通过对现有存储库进行最少的
  • 设置 git 别名,但调用它会给出“找不到命令”

    我想在 git 中设置一个别名来计算存储库中的总行数 因此我进入 Git Bash 并输入以下内容 git config global alias linecount ls files z xargs 0 wc l 我输入命令后 没有出现错

随机推荐