行删除已经完成,但没有责任归咎于承诺
Lines deletions has been done but there is no commit to blame
某些行已从文件中删除,我想知道它是何时以及如何发生的。
但是:没有发现错误的提交。真奇怪。
这里是 git log
,它显示(作为最后更改)添加行时的提交:
$ git log --follow -p -- src/QsGeneralBundle/Repository/EmployeeRepository.php
commit 80dc439aba2bf38ed7e95888dd21c1ba0f8960ce
Author: Benoit <benoit.guchet@gmail.Com>
Date: Tue Jul 16 18:31:38 2019 +0200
Opti Doctrine #814
diff --git a/src/QsGeneralBundle/Repository/EmployeeRepository.php b/src/QsGeneralBundle/Repository/EmployeeRepository.php
index 7dfc2f963..a3e916690 100644
--- a/src/QsGeneralBundle/Repository/EmployeeRepository.php
+++ b/src/QsGeneralBundle/Repository/EmployeeRepository.php
@@ -10,12 +10,15 @@ namespace QsGeneralBundle\Repository;
*/
class EmployeeRepository extends BaseRepository
{
- public function findAllQb() {
- $qb = $this->createQueryBuilder('e')
+ public function findAllQb() {
+ $qb = $this->createQueryBuilder('e')
->innerJoin('e.Account', 'a')
- ->orderBy('a.firstname', 'ASC')
- ->addOrderBy('a.lastname', 'ASC')
- ->andWhere('a.isEnabled = TRUE');
+ ->leftJoin('a.SpecificRole', 'r')
+ ->leftJoin('a.Contractor', 'c')
+ ->orderBy('a.firstname', 'ASC')
+ ->addOrderBy('a.lastname', 'ASC')
+ ->andWhere('a.isEnabled = TRUE')
+ ->select('e, a, r, c');
return $qb;
}
现在这是文件的当前内容:
<?php
namespace QsGeneralBundle\Repository;
/**
* Created by IntelliJ IDEA.
* User: Benoît Guchet
* Date: 16/11/2016
* Time: 13:26
*/
class EmployeeRepository extends BaseRepository
{
public function findAllQb() {
$qb = $this->createQueryBuilder('e')
->innerJoin('e.Account', 'a')
->orderBy('a.firstname', 'ASC')
->addOrderBy('a.lastname', 'ASC')
->andWhere('a.isEnabled = TRUE');
return $qb;
}
}
没有本地变化,如 git status
:
$ git status src/QsGeneralBundle/Repository/EmployeeRepository.php
On branch master
Your branch is ahead of 'origin/master' by 11 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
对这个谜团有什么想法吗?
假设 src/QsGeneralBundle/Repository/EmployeeRepository.php
从未被重命名(或不在将显示的提交范围内),您可以省略 --follow
并添加 --full-history
和 -m
.
这里有两个问题:
首先,您要查找的更改可能发生在合并期间。如果没有 -m
(或其他一些也不是默认参数),git log
将忽略合并期间提交的 所有 更改。
其次,当你指定一个文件名如src/QsGeneralBundle/Repository/EmployeeRepository.php
(有或没有--follow
)时,Git开启History Simplification 。当历史简化开启时,Git 只是 懒得去查看 某些提交。特别是,它不会遵循合并的分支(incorectly-但请参阅脚注)不会 采取 您认为合并 应该 [=174] 的更改=]取.
因此,通过强制历史简化保留所有提交 (--full-history
) 并强制 git log
将合并提交显示为 two git diff
s,你应该能够找到你想要的提交被(错误地)丢弃的地方。
脚注:Git 假设每次合并的结果都是正确的 结果。也就是说,假设合并提交在其 right-side incoming-branch 更改时有错误修复,并且在其 left-side 更改时根本没有更改。进一步假设进行合并的人放弃了错误修复:
o another commit (has bug)
|
* merge commit (has bug, person who merged dropped the fix)
|\
o | main line work (has bug)
| |
| o fix for bug
|/
o main line work (has bug)
Git 假设 right-side 更改(错误修复)是 介绍 错误,进行合并的人很聪明并省略了,保留了 left-side 版本(根据进行合并的人,因此现在根据 Git也是)是 "correct"。事实上,合并提交是 错误的 ... 但是当 Git 进行历史简化时,Git 认为它是正确的。因此 Git 此时仅跟随提交图的左侧。你永远看不到错误修复!
查看修复提交的唯一方法是避免或禁用历史简化(省略文件名,或添加 --full-history
)。但是由于默认情况下,git log -p
不会将合并提交与 bug-fix 提交进行区分,即使这样也是不够的。
附加脚注:请注意 Git 中的文件名是 完整路径 。如果一个文件被命名为 a/b/c.ext
,现在被命名为 a/d/c.ext
,这个文件有两个不同的名字。 Git不存储目录/文件夹,即why you cannot store an empty directory。 (脚注的旁注:是每个存储库中的一个空树对象,但使用它会导致稍后出现问题,因为Git一直试图将其转换为子模块——参见有关详细信息的链接问题。)
Git 处理您的计算机坚持使用目录/文件夹的方式——这就是允许您的 OS 提供 空 的方式——是宠爱你的 OS。 Git 只是提取 文件 进行提交,如果您的 OS 要求创建 Git-name 为 a/b/c.ext
的文件作为文件夹 b
中的文件 c.ext
在文件夹 a
中,然后,Git 创建文件夹 a
,然后创建文件夹 a/b
,以便创建一个名称为 a/b/c.ext
的文件。如果有没有个名称以a/b
开头的文件,Git就不会创建 a/b
首先。
无论如何,--follow
的根本问题是它的实现是一个俗气的 hack。假设历史——即存储库中的 backwards-looking 提交链——看起来像这样,后面的提交向右:
...--I--J
\
M--N <-- branch
/
...--K--L
其中每个字母代表一个实际的提交散列。在提交 N
中,您有一个名为 a/d/c.ext
的文件;在提交 I
中,同一个文件的名称为 a/b/c.ext
。 git log --follow a/d/c.ext
处理这个的方式就是看每一个commit-pair,一步一个脚印:
首先,Git查看M-N
对。
M
中的文件名为a/b/c.ext
,N
中的文件名为a/d/c.ext
吗?如果是这样,那么一旦 Git 在 J-M
和 L-M
对上工作,Git 将 停止 寻找 a/d/c.ext
并开始寻找 a/b/c.ext
(旧名称,而不是当前名称)。
如果不是——如果在M
中仍然是a/d/c.ext
——那么当Git比较J
和M
,或者比较L
和 M
,它将查找 a/d/c.ext
(当前名称,而不是旧名称)。
接下来,Git 查看 J-M
或 L-M
对——或者,如果进行历史简化而不是强制 not to, 挑一对看,并没有真正看另一对,也没有跟随分支的那条腿。
如果文件在其中一对中重命名,而不是另一对,Git 真的无法处理。没有 --full-history
Git 将选择一条腿跟随,并且在某种程度上假装没有合并并且重命名检测可以 wrk(虽然我不确定它确实如此,但考虑到 git log
在合并周围显示的其他奇怪之处)。如果文件没有在 或 对中重命名,但是,我们仍然很好:文件仍然有它的新名称,所以如果我们强制 --full-history
,那么 Git 现在必须遍历合并的两个分支,Git 会这样做。假设它现在执行 I-J
部分:
现在 Git 比较提交 I
和 J
。文件在这里重命名了吗? 假设它在这里被重命名了。实际上,Git 对自己说:啊哈,让我们停止寻找 a/d/c.ext
;从现在开始,让我们寻找 a/b/c.ext
. 当 Git 将提交 I
与提交 I
之前的任何内容进行比较时,就可以了。
但是,在跟踪合并的这段时间后,Git 现在——无论如何在 --full-history
下——返回并比较提交 K
和 L
,来自合并的 other 分支。 Git 去检查文件 a/b/c.ext
,因为这是它现在认为文件具有的路径。 但是文件在合并的这个分支中仍然有a/d/c.ext
名称。结果是git log --follow
正在寻找错误的文件!
要使这一切正常进行,git log --follow
需要比实际情况更聪明。 --follow
所做的只是更改 它正在寻找的一个文件名 ,并且它不记得它在某些特定的 部分 中这样做了] 的提交图。 Git 需要以某种方式将名称更改与图形遍历联系起来,并且 "undo" 每当它返回 "up" 图形时更改(但 Git 并没有真正上升:它实际上只是将提交放入优先级队列,这意味着没有地方可以放置此 name-change 信息)。
如果所有的名称更改都发生在"right"处,--follow
和--full-history
可以混合使用。例如,如果旧名称 a/b/c.ext
的 name-change 到 a/d/c.ext
出现在 M-N
对中,那么 all提交具有旧名称 - 然后 --follow
和 --full-history
在合并的两条腿之后没有问题:该文件只有历史上 M
的一个名称和 --follow
在正确的时间更改一个名称。当 name-change 发生在 平行 历史中,在多个不同的合并分支中,这就搞砸了。
某些行已从文件中删除,我想知道它是何时以及如何发生的。
但是:没有发现错误的提交。真奇怪。
这里是 git log
,它显示(作为最后更改)添加行时的提交:
$ git log --follow -p -- src/QsGeneralBundle/Repository/EmployeeRepository.php
commit 80dc439aba2bf38ed7e95888dd21c1ba0f8960ce
Author: Benoit <benoit.guchet@gmail.Com>
Date: Tue Jul 16 18:31:38 2019 +0200
Opti Doctrine #814
diff --git a/src/QsGeneralBundle/Repository/EmployeeRepository.php b/src/QsGeneralBundle/Repository/EmployeeRepository.php
index 7dfc2f963..a3e916690 100644
--- a/src/QsGeneralBundle/Repository/EmployeeRepository.php
+++ b/src/QsGeneralBundle/Repository/EmployeeRepository.php
@@ -10,12 +10,15 @@ namespace QsGeneralBundle\Repository;
*/
class EmployeeRepository extends BaseRepository
{
- public function findAllQb() {
- $qb = $this->createQueryBuilder('e')
+ public function findAllQb() {
+ $qb = $this->createQueryBuilder('e')
->innerJoin('e.Account', 'a')
- ->orderBy('a.firstname', 'ASC')
- ->addOrderBy('a.lastname', 'ASC')
- ->andWhere('a.isEnabled = TRUE');
+ ->leftJoin('a.SpecificRole', 'r')
+ ->leftJoin('a.Contractor', 'c')
+ ->orderBy('a.firstname', 'ASC')
+ ->addOrderBy('a.lastname', 'ASC')
+ ->andWhere('a.isEnabled = TRUE')
+ ->select('e, a, r, c');
return $qb;
}
现在这是文件的当前内容:
<?php
namespace QsGeneralBundle\Repository;
/**
* Created by IntelliJ IDEA.
* User: Benoît Guchet
* Date: 16/11/2016
* Time: 13:26
*/
class EmployeeRepository extends BaseRepository
{
public function findAllQb() {
$qb = $this->createQueryBuilder('e')
->innerJoin('e.Account', 'a')
->orderBy('a.firstname', 'ASC')
->addOrderBy('a.lastname', 'ASC')
->andWhere('a.isEnabled = TRUE');
return $qb;
}
}
没有本地变化,如 git status
:
$ git status src/QsGeneralBundle/Repository/EmployeeRepository.php
On branch master
Your branch is ahead of 'origin/master' by 11 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
对这个谜团有什么想法吗?
假设 src/QsGeneralBundle/Repository/EmployeeRepository.php
从未被重命名(或不在将显示的提交范围内),您可以省略 --follow
并添加 --full-history
和 -m
.
这里有两个问题:
首先,您要查找的更改可能发生在合并期间。如果没有
-m
(或其他一些也不是默认参数),git log
将忽略合并期间提交的 所有 更改。其次,当你指定一个文件名如
src/QsGeneralBundle/Repository/EmployeeRepository.php
(有或没有--follow
)时,Git开启History Simplification 。当历史简化开启时,Git 只是 懒得去查看 某些提交。特别是,它不会遵循合并的分支(incorectly-但请参阅脚注)不会 采取 您认为合并 应该 [=174] 的更改=]取.
因此,通过强制历史简化保留所有提交 (--full-history
) 并强制 git log
将合并提交显示为 two git diff
s,你应该能够找到你想要的提交被(错误地)丢弃的地方。
脚注:Git 假设每次合并的结果都是正确的 结果。也就是说,假设合并提交在其 right-side incoming-branch 更改时有错误修复,并且在其 left-side 更改时根本没有更改。进一步假设进行合并的人放弃了错误修复:
o another commit (has bug)
|
* merge commit (has bug, person who merged dropped the fix)
|\
o | main line work (has bug)
| |
| o fix for bug
|/
o main line work (has bug)
Git 假设 right-side 更改(错误修复)是 介绍 错误,进行合并的人很聪明并省略了,保留了 left-side 版本(根据进行合并的人,因此现在根据 Git也是)是 "correct"。事实上,合并提交是 错误的 ... 但是当 Git 进行历史简化时,Git 认为它是正确的。因此 Git 此时仅跟随提交图的左侧。你永远看不到错误修复!
查看修复提交的唯一方法是避免或禁用历史简化(省略文件名,或添加 --full-history
)。但是由于默认情况下,git log -p
不会将合并提交与 bug-fix 提交进行区分,即使这样也是不够的。
附加脚注:请注意 Git 中的文件名是 完整路径 。如果一个文件被命名为 a/b/c.ext
,现在被命名为 a/d/c.ext
,这个文件有两个不同的名字。 Git不存储目录/文件夹,即why you cannot store an empty directory。 (脚注的旁注:是每个存储库中的一个空树对象,但使用它会导致稍后出现问题,因为Git一直试图将其转换为子模块——参见有关详细信息的链接问题。)
Git 处理您的计算机坚持使用目录/文件夹的方式——这就是允许您的 OS 提供 空 的方式——是宠爱你的 OS。 Git 只是提取 文件 进行提交,如果您的 OS 要求创建 Git-name 为 a/b/c.ext
的文件作为文件夹 b
中的文件 c.ext
在文件夹 a
中,然后,Git 创建文件夹 a
,然后创建文件夹 a/b
,以便创建一个名称为 a/b/c.ext
的文件。如果有没有个名称以a/b
开头的文件,Git就不会创建 a/b
首先。
无论如何,--follow
的根本问题是它的实现是一个俗气的 hack。假设历史——即存储库中的 backwards-looking 提交链——看起来像这样,后面的提交向右:
...--I--J
\
M--N <-- branch
/
...--K--L
其中每个字母代表一个实际的提交散列。在提交 N
中,您有一个名为 a/d/c.ext
的文件;在提交 I
中,同一个文件的名称为 a/b/c.ext
。 git log --follow a/d/c.ext
处理这个的方式就是看每一个commit-pair,一步一个脚印:
首先,Git查看
M-N
对。M
中的文件名为a/b/c.ext
,N
中的文件名为a/d/c.ext
吗?如果是这样,那么一旦 Git 在J-M
和L-M
对上工作,Git 将 停止 寻找a/d/c.ext
并开始寻找a/b/c.ext
(旧名称,而不是当前名称)。如果不是——如果在
M
中仍然是a/d/c.ext
——那么当Git比较J
和M
,或者比较L
和M
,它将查找a/d/c.ext
(当前名称,而不是旧名称)。接下来,Git 查看
J-M
或L-M
对——或者,如果进行历史简化而不是强制 not to, 挑一对看,并没有真正看另一对,也没有跟随分支的那条腿。如果文件在其中一对中重命名,而不是另一对,Git 真的无法处理。没有
--full-history
Git 将选择一条腿跟随,并且在某种程度上假装没有合并并且重命名检测可以 wrk(虽然我不确定它确实如此,但考虑到git log
在合并周围显示的其他奇怪之处)。如果文件没有在 或 对中重命名,但是,我们仍然很好:文件仍然有它的新名称,所以如果我们强制--full-history
,那么 Git 现在必须遍历合并的两个分支,Git 会这样做。假设它现在执行I-J
部分:现在 Git 比较提交
I
和J
。文件在这里重命名了吗? 假设它在这里被重命名了。实际上,Git 对自己说:啊哈,让我们停止寻找a/d/c.ext
;从现在开始,让我们寻找a/b/c.ext
. 当 Git 将提交I
与提交I
之前的任何内容进行比较时,就可以了。但是,在跟踪合并的这段时间后,Git 现在——无论如何在
--full-history
下——返回并比较提交K
和L
,来自合并的 other 分支。 Git 去检查文件a/b/c.ext
,因为这是它现在认为文件具有的路径。 但是文件在合并的这个分支中仍然有a/d/c.ext
名称。结果是git log --follow
正在寻找错误的文件!
要使这一切正常进行,git log --follow
需要比实际情况更聪明。 --follow
所做的只是更改 它正在寻找的一个文件名 ,并且它不记得它在某些特定的 部分 中这样做了] 的提交图。 Git 需要以某种方式将名称更改与图形遍历联系起来,并且 "undo" 每当它返回 "up" 图形时更改(但 Git 并没有真正上升:它实际上只是将提交放入优先级队列,这意味着没有地方可以放置此 name-change 信息)。
如果所有的名称更改都发生在"right"处,--follow
和--full-history
可以混合使用。例如,如果旧名称 a/b/c.ext
的 name-change 到 a/d/c.ext
出现在 M-N
对中,那么 all提交具有旧名称 - 然后 --follow
和 --full-history
在合并的两条腿之后没有问题:该文件只有历史上 M
的一个名称和 --follow
在正确的时间更改一个名称。当 name-change 发生在 平行 历史中,在多个不同的合并分支中,这就搞砸了。