Git 自行分支
Git branching on its own
我一直在我作为独立贡献者的存储库中使用 git。存储库托管在 Github 上。出于某种原因,git 偶尔似乎在 Github 上分支,而我没有做任何改变。我只在一台计算机上更改此 repo,并且不在 Github 上修改任何东西。然而,正如您在 git log --oneline --decorate --graph --all
的这个缩短的选择中看到的那样,我似乎不得不随机执行此操作。提交 271056c
在 Github 的 cfacddf
处重复。
这可能是什么原因造成的?这是一个错误吗?
我现在考虑的可能理论:这可能是 git commit --amend
的结果吗?
git log --oneline --decorate --graph --all
的输出:
* d030d88 (HEAD -> master, origin/master, origin/HEAD) Merge branch 'master' of ***
|\
| * cfacddf Fixed a few things:
* | 798afef modified: tasks.txt
* | 2c19ea0 Paginated:
* | 271056c Fixed a few things:
|/
* 63a429c Added lock icon to annotation headers
git log
的输出:
commit d030d8820456b0f129d2d3e5167ed88f87ebe028
Merge: 798afef cfacddf
Author: ***
Date: Wed Oct 3 16:49:00 2018 -0400
Merge branch 'master' of https://github.com/malan88/icc
commit 798afefabe24027a955853771072755c08318b47
Author: Michael Alan <michaelalantarpon@gmail.com>
Date: Wed Oct 3 16:48:54 2018 -0400
modified: tasks.txt
commit 2c19ea0b735d148f0057852c196254c4258c2c6b
Author: ***
Date: Wed Oct 3 16:42:20 2018 -0400
Paginated:
- Author index
- Book index
- User Annotations
- Tag index
commit 271056c1c34444dbb3b8c2b6a67efae67f27b44b
Author: ***
Date: Wed Oct 3 15:24:14 2018 -0400
Fixed a few things:
- hash_id bug
- line_number_form on read.html bug
- horribly inefficient permissions check on line edits on read.html
- Added lock change mechanism for when admin doesn't want to edit
annotation
- cleaned up some bad whitespace
- Bug that didn't include query parameters in next parameter (e.g.
pagenumbers, etc)
commit cfacddfb5395e0fa3676fbc1e19457c45c7c3529
Author: ***
Date: Wed Oct 3 15:24:14 2018 -0400
Fixed a few things:
- hash_id bug
- line_number_form on read.html bug
- horribly inefficient permissions check on line edits on read.html
- Added lock change mechanism for when admin doesn't want to edit
annotation
- cleaned up some bad whitespace
- Bug that didn't include query parameters in next parameter (e.g.
pagenumbers, etc)
commit cfacddfb5395e0fa3676fbc1e19457c45c7c3529
Author: ***
Date: Wed Oct 3 15:24:14 2018 -0400
Fixed a few things:
- hash_id bug
- line_number_form on read.html bug
- horribly inefficient permissions check on line edits on read.html
- Added lock change mechanism for when admin doesn't want to edit
annotation
- cleaned up some bad whitespace
commit 63a429c828cec06fa30e4994f3912fab387c7a4c
Author: ***
Date: Wed Oct 3 15:21:58 2018 -0400
Added lock icon to annotation headers
让我们从这里开始:
Possible theory I now consider: could it be the result of git commit --amend
?
是。
现在让我们回到这个,因为这里有一个隐藏的假设,这是一个关键因素:
I have been using git in a repository for which I am the solo contributor. The repository is hosted on GitHub.
这不太对。您在这里的意思是 a 存储库位于 GitHub 上。它不是 存储库:它是几个或多个存储库之一。在本例中,它是两者之一。另一个在你自己的机器上!
要获得正确的解释,请参阅我的许多较长答案中的任何一个。另请参阅网站 Think Like (a) Git,其中有很多重要的背景信息。但简而言之,请记住这里有两个存储库:您的存储库和 GitHub 上的 Git 存储库。
当您进行提交时,它由其哈希 ID 唯一标识 - 一大串难看的十六进制数字,例如 cfacddfb5395e0fa3676fbc1e19457c45c7c3529
。这就是您的 Git 存储在您的 b运行ch 名称 master
中的内容。每个提交还存储其前一个或 parent、提交的哈希 ID。合并提交是至少有两个 parent 的提交。当 b运行ch 名称或提交存储提交的哈希 ID 时,我们说此名称或此提交 指向 目标提交。
我们可以绘制诸如(水平方向)图表之类的东西,最新的提交向右:
...<-F <-G <-H <--master
Git 将名称 HEAD
附加到一个 b运行ch 名称,这样如果您有多个 b运行ch 名称,它就知道哪个是您当前的 b 运行通道。提交中的箭头不能改变——任何提交中的任何东西都不能永远改变——所以我们真的不需要绘制内部箭头:
...--F--G--H <-- master (HEAD)
当你 运行 git commit
时,正常的程序是将索引中的任何内容冻结到一个新的快照中,使快照的 parent 成为 当前提交,使用来自 HEAD
附加的 b运行ch 名称的指针:
...--F--G--H--I
然后 Git 将 new 提交的哈希 ID 放入当前的 b运行ch 名称中,以便它现在指向新的提交:
...--F--G--H--I <-- master (HEAD)
git commit --amend
的工作原理
我们刚刚看到 git commit
:
- 将当前索引冻结到快照中;
- 写出一个新的提交,当前提交作为它的 parent;
- 将新提交的哈希写入当前 b运行ch。
--amend
所做的只是更改为更改步骤2:不是使用当前提交作为新提交的parent,--amend
使用当前提交的parents 作为新提交的 parents。 (如果有多个 parents——如果当前提交是一个合并——新提交获取当前提交的所有 parents。如果是正常的 single-parent non-merge提交,新提交得到一个新的 parent。)所以我们得到:
而不是从 ...-F-G-H
到 ...-F-G-H-I
H
/
...--F--G--I <-- master (HEAD)
也就是说,--amend
将当前提交推开。
如果你没有推送,这很好用
如果您从未将提交 H
推送到任何地方,现在修改它可以正常工作。新提交 I
接管; commit H
消失了,再也见不到了。 (您可以在自己的存储库中找到它一段时间——默认情况下至少 30 天,直到记住它的 reflog 条目过期。但它不会出现在正常的 git log
输出中。)
但是如果你有
它会失败
但是如果你已经将提交H
发送到另一个Git——比如你存储在GitHub上的存储库——那么任何时候你联系 他们,他们都会再次向你提交 H
,因为这是对 他们 [=22] 的重要提交=]b运行ch。这就是本案中发生的事情。
您已将提交 H
推送到 GitHub。然后你让你的 Git 把你的 H
推开,如上所述,但是 GitHub 仍然有 H
。您的 Git 记住了这一点,但如果您的 Git 忘记了或者您删除了它的记忆,您的 Git 会在您下次 Git 调用 Git 在 Git 中心。所以现在你有了这个:
H <-- origin/master
/
...--F--G--I <-- master (HEAD)
从现在开始,当您在您的存储库中工作时,提交 H
仍然可见。您提交了 J
(271056c1c34444dbb3b8c2b6a67efae67f27b44b
) 和 K
(798afefabe24027a955853771072755c08318b47
):
H <-- origin/master
/
...--F--G--I--J--K <-- master (HEAD)
此时,你 运行 git pull
,你的 Git 在 GitHub 调用 Git 并从中获取任何新提交GitHub(有 none)并更新你的 origin/master
以匹配他们的 master
(仍然指向提交 H
)。你的 git pull
然后让你的 Git 合并 他们的提交 H
和你的提交 K
,进行新的 two-parent 合并提交 L
:
H_ <-- origin/master
/ `----__
...--F--G--I--J--K-=L <-- master (HEAD)
这就是您现在看到的。 (好吧,现在 你还要求 GitHub Git 将他们的 master
设置为 L
,他们这样做了,所以你的自己的 Git 存储库的 origin/master
也转到 L
。)
要修复它,您必须让所有其他 Git 忘记 H
在你之后"amend" H
,你必须找到所有其他 Git 有 H
的存储库,并说服他们改用 I
。在这种情况下,只涉及另一个 Git:位于 GitHub 的那个。你可以 运行:
git push origin master
您的 Git 在 Git 中心调用 Git 并礼貌地请求他们更改 master
以指向您的替换提交 I
.但是如果你这样做,你会发现他们说不,我不会那样做,因为那样会失去commit H
. 这种抱怨的形式是:
! [rejected] master -> master (non-fast-forward)
在这种情况下,您知道问题出在哪里,并且您希望他们丢失(忘记)提交H
。所以你可以使用 git push --force
或更高级的变体 git push --force-with-lease
.
这些将您的请求(请更新您的master
)转换为命令:更新您的master
! GitHub 仍然可以拒绝(如果您没有被授权这样做,也会拒绝),但一般来说,他们会服从他们拒绝请求的命令。 --force-with-lease
选项用作安全检查:而不只是说 无论如何都要这样做 ,你的 Git 对他们说:我认为你有你的 master 设置为 。如果是这样,请更换它。如果没有,请告诉我。 这是您可以在共享存储库上使用的内容,以防其他人也推送到 GitHub master
.
我一直在我作为独立贡献者的存储库中使用 git。存储库托管在 Github 上。出于某种原因,git 偶尔似乎在 Github 上分支,而我没有做任何改变。我只在一台计算机上更改此 repo,并且不在 Github 上修改任何东西。然而,正如您在 git log --oneline --decorate --graph --all
的这个缩短的选择中看到的那样,我似乎不得不随机执行此操作。提交 271056c
在 Github 的 cfacddf
处重复。
这可能是什么原因造成的?这是一个错误吗?
我现在考虑的可能理论:这可能是 git commit --amend
的结果吗?
git log --oneline --decorate --graph --all
的输出:
* d030d88 (HEAD -> master, origin/master, origin/HEAD) Merge branch 'master' of ***
|\
| * cfacddf Fixed a few things:
* | 798afef modified: tasks.txt
* | 2c19ea0 Paginated:
* | 271056c Fixed a few things:
|/
* 63a429c Added lock icon to annotation headers
git log
的输出:
commit d030d8820456b0f129d2d3e5167ed88f87ebe028
Merge: 798afef cfacddf
Author: ***
Date: Wed Oct 3 16:49:00 2018 -0400
Merge branch 'master' of https://github.com/malan88/icc
commit 798afefabe24027a955853771072755c08318b47
Author: Michael Alan <michaelalantarpon@gmail.com>
Date: Wed Oct 3 16:48:54 2018 -0400
modified: tasks.txt
commit 2c19ea0b735d148f0057852c196254c4258c2c6b
Author: ***
Date: Wed Oct 3 16:42:20 2018 -0400
Paginated:
- Author index
- Book index
- User Annotations
- Tag index
commit 271056c1c34444dbb3b8c2b6a67efae67f27b44b
Author: ***
Date: Wed Oct 3 15:24:14 2018 -0400
Fixed a few things:
- hash_id bug
- line_number_form on read.html bug
- horribly inefficient permissions check on line edits on read.html
- Added lock change mechanism for when admin doesn't want to edit
annotation
- cleaned up some bad whitespace
- Bug that didn't include query parameters in next parameter (e.g.
pagenumbers, etc)
commit cfacddfb5395e0fa3676fbc1e19457c45c7c3529
Author: ***
Date: Wed Oct 3 15:24:14 2018 -0400
Fixed a few things:
- hash_id bug
- line_number_form on read.html bug
- horribly inefficient permissions check on line edits on read.html
- Added lock change mechanism for when admin doesn't want to edit
annotation
- cleaned up some bad whitespace
- Bug that didn't include query parameters in next parameter (e.g.
pagenumbers, etc)
commit cfacddfb5395e0fa3676fbc1e19457c45c7c3529
Author: ***
Date: Wed Oct 3 15:24:14 2018 -0400
Fixed a few things:
- hash_id bug
- line_number_form on read.html bug
- horribly inefficient permissions check on line edits on read.html
- Added lock change mechanism for when admin doesn't want to edit
annotation
- cleaned up some bad whitespace
commit 63a429c828cec06fa30e4994f3912fab387c7a4c
Author: ***
Date: Wed Oct 3 15:21:58 2018 -0400
Added lock icon to annotation headers
让我们从这里开始:
Possible theory I now consider: could it be the result of
git commit --amend
?
是。
现在让我们回到这个,因为这里有一个隐藏的假设,这是一个关键因素:
I have been using git in a repository for which I am the solo contributor. The repository is hosted on GitHub.
这不太对。您在这里的意思是 a 存储库位于 GitHub 上。它不是 存储库:它是几个或多个存储库之一。在本例中,它是两者之一。另一个在你自己的机器上!
要获得正确的解释,请参阅我的许多较长答案中的任何一个。另请参阅网站 Think Like (a) Git,其中有很多重要的背景信息。但简而言之,请记住这里有两个存储库:您的存储库和 GitHub 上的 Git 存储库。
当您进行提交时,它由其哈希 ID 唯一标识 - 一大串难看的十六进制数字,例如 cfacddfb5395e0fa3676fbc1e19457c45c7c3529
。这就是您的 Git 存储在您的 b运行ch 名称 master
中的内容。每个提交还存储其前一个或 parent、提交的哈希 ID。合并提交是至少有两个 parent 的提交。当 b运行ch 名称或提交存储提交的哈希 ID 时,我们说此名称或此提交 指向 目标提交。
我们可以绘制诸如(水平方向)图表之类的东西,最新的提交向右:
...<-F <-G <-H <--master
Git 将名称 HEAD
附加到一个 b运行ch 名称,这样如果您有多个 b运行ch 名称,它就知道哪个是您当前的 b 运行通道。提交中的箭头不能改变——任何提交中的任何东西都不能永远改变——所以我们真的不需要绘制内部箭头:
...--F--G--H <-- master (HEAD)
当你 运行 git commit
时,正常的程序是将索引中的任何内容冻结到一个新的快照中,使快照的 parent 成为 当前提交,使用来自 HEAD
附加的 b运行ch 名称的指针:
...--F--G--H--I
然后 Git 将 new 提交的哈希 ID 放入当前的 b运行ch 名称中,以便它现在指向新的提交:
...--F--G--H--I <-- master (HEAD)
git commit --amend
的工作原理
我们刚刚看到 git commit
:
- 将当前索引冻结到快照中;
- 写出一个新的提交,当前提交作为它的 parent;
- 将新提交的哈希写入当前 b运行ch。
--amend
所做的只是更改为更改步骤2:不是使用当前提交作为新提交的parent,--amend
使用当前提交的parents 作为新提交的 parents。 (如果有多个 parents——如果当前提交是一个合并——新提交获取当前提交的所有 parents。如果是正常的 single-parent non-merge提交,新提交得到一个新的 parent。)所以我们得到:
...-F-G-H
到 ...-F-G-H-I
H
/
...--F--G--I <-- master (HEAD)
也就是说,--amend
将当前提交推开。
如果你没有推送,这很好用
如果您从未将提交 H
推送到任何地方,现在修改它可以正常工作。新提交 I
接管; commit H
消失了,再也见不到了。 (您可以在自己的存储库中找到它一段时间——默认情况下至少 30 天,直到记住它的 reflog 条目过期。但它不会出现在正常的 git log
输出中。)
但是如果你有
它会失败但是如果你已经将提交H
发送到另一个Git——比如你存储在GitHub上的存储库——那么任何时候你联系 他们,他们都会再次向你提交 H
,因为这是对 他们 [=22] 的重要提交=]b运行ch。这就是本案中发生的事情。
您已将提交 H
推送到 GitHub。然后你让你的 Git 把你的 H
推开,如上所述,但是 GitHub 仍然有 H
。您的 Git 记住了这一点,但如果您的 Git 忘记了或者您删除了它的记忆,您的 Git 会在您下次 Git 调用 Git 在 Git 中心。所以现在你有了这个:
H <-- origin/master
/
...--F--G--I <-- master (HEAD)
从现在开始,当您在您的存储库中工作时,提交 H
仍然可见。您提交了 J
(271056c1c34444dbb3b8c2b6a67efae67f27b44b
) 和 K
(798afefabe24027a955853771072755c08318b47
):
H <-- origin/master
/
...--F--G--I--J--K <-- master (HEAD)
此时,你 运行 git pull
,你的 Git 在 GitHub 调用 Git 并从中获取任何新提交GitHub(有 none)并更新你的 origin/master
以匹配他们的 master
(仍然指向提交 H
)。你的 git pull
然后让你的 Git 合并 他们的提交 H
和你的提交 K
,进行新的 two-parent 合并提交 L
:
H_ <-- origin/master
/ `----__
...--F--G--I--J--K-=L <-- master (HEAD)
这就是您现在看到的。 (好吧,现在 你还要求 GitHub Git 将他们的 master
设置为 L
,他们这样做了,所以你的自己的 Git 存储库的 origin/master
也转到 L
。)
要修复它,您必须让所有其他 Git 忘记 H
在你之后"amend" H
,你必须找到所有其他 Git 有 H
的存储库,并说服他们改用 I
。在这种情况下,只涉及另一个 Git:位于 GitHub 的那个。你可以 运行:
git push origin master
您的 Git 在 Git 中心调用 Git 并礼貌地请求他们更改 master
以指向您的替换提交 I
.但是如果你这样做,你会发现他们说不,我不会那样做,因为那样会失去commit H
. 这种抱怨的形式是:
! [rejected] master -> master (non-fast-forward)
在这种情况下,您知道问题出在哪里,并且您希望他们丢失(忘记)提交H
。所以你可以使用 git push --force
或更高级的变体 git push --force-with-lease
.
这些将您的请求(请更新您的master
)转换为命令:更新您的master
! GitHub 仍然可以拒绝(如果您没有被授权这样做,也会拒绝),但一般来说,他们会服从他们拒绝请求的命令。 --force-with-lease
选项用作安全检查:而不只是说 无论如何都要这样做 ,你的 Git 对他们说:我认为你有你的 master 设置为 master
.