在GitHub上更改作者信息后,应该执行哪些本地操作?

在GitHub上更改作者信息后,应该执行哪些本地操作?,git,rebase,Git,Rebase,我想从提交到GitHub repo的过程中删除个人电子邮件地址,因此我遵循Git Bash,它在临时克隆repo中使用Git筛选器分支更新受影响的提交,最后运行以下命令: git push --force --tags origin 'refs/heads/*' 现在,在GitHub上,回购协议看起来是正确的,电子邮件已经清理干净。然而,我对Git还不熟悉,不确定我需要做什么后续工作来同步我的本地副本 当我尝试拉取时,会出现错误“拒绝合并不相关的历史记录” 在此之前,我没有在本地进行任何更改,

我想从提交到GitHub repo的过程中删除个人电子邮件地址,因此我遵循Git Bash,它在临时克隆repo中使用
Git筛选器分支
更新受影响的提交,最后运行以下命令:

git push --force --tags origin 'refs/heads/*'
现在,在GitHub上,回购协议看起来是正确的,电子邮件已经清理干净。然而,我对Git还不熟悉,不确定我需要做什么后续工作来同步我的本地副本

当我尝试拉取时,会出现错误“拒绝合并不相关的历史记录”

在此之前,我没有在本地进行任何更改,所以可能最简单的方法就是删除我的本地回购协议,然后再次签出该项目,但据我所知,这不是最佳做法或最灵活的方式

似乎我需要重新审视重写的历史,可能是这样的:

git pull --rebase
这是最好的办法吗?如果没有,是什么


旁注:我在IntelliJ IDEA中工作,理想情况下,仅将cmd行用于编写更改脚本等不寻常的事情,其Pull对话框没有Rebase选项,但Update Project有,所以我实际上就是这么做的。这是对的吗?

无论您选择什么过程来同步本地回购,最终结果都是一样的:两个回购都具有相同的历史记录。在这种情况下,本地版本将被远程版本覆盖

因此,由于您没有本地更改需要保留,很可能没有什么比您考虑的再次克隆项目更干净、更快的了。我会说去做吧


(作为旁注,我看不出这是一种不好的做法的任何原因。您预见到了什么具体问题?

当您像这样重写历史时,您可以而且您的案例确实得到了一个新的、不同的存储库。在这种情况下,旧存储库的所有现有克隆仅可用于旧存储库。现在,您只需创建新存储库的新克隆,这是一个新项目,您永远不应该连接到旧项目:这两个项目不再兼容,提交也不能再从一个项目转移到另一个项目

这是一个复杂现实的简化视图,但它应该满足您的情况。如果你想了解现实,请继续阅读

Git主要关心提交,但提交到底是什么? Git存储库的本质是一对数据库。大型数据库包含所有提交,或者更准确地说,包含所有Git对象。(Git对象有四种类型:commit、tree、blob和annotated tag。tree和blob是commit在其内部存储文件的方式,而annotated tag对象只是用来保存带注释的标记数据。)每个唯一的Git对象都有一个唯一的散列ID,因此每个commit都有自己唯一的散列ID,与其他每次commit不同

所有这些散列ID不仅是唯一的,而且是通用的。这意味着宇宙中任何地方的每个Git都使用相同的GUID进行提交

Git实际实现这一点的方式是,ID是提交内容的加密校验和。这意味着在提交中几乎不可能更改任何内容:如果您确实设法更改了某些内容,那么您将得到一个新的、不同的提交,并使用一个新的、不同的哈希ID。给定哈希ID,Git可以检查它是否有对象。如果是这样,它可以检索对象。如果没有,您的Git可以向其他Git(有对象的Git)请求完整的对象,并将结果对象填充到它的大数据库中

每当我们有散列ID并且实际对象在数据库中时,我们就说我们有一个指向该对象的指针。这些指针让我们可以找到提交(或其他Git对象,但主要是使用提交)

在任何情况下,提交的实际内容通常都很短:每次提交都会保存该提交文件快照的哈希ID,这是您要永久保留的数据,再加上一组元数据,如您的姓名和电子邮件地址。不过,每次提交的元数据片段之一是提交的父哈希ID(如果提交是合并提交,则为复数ID)。因此,每个提交都通过散列ID指向其父级

我们可以画出这个,如果我们使用单大写字母来表示提交,它甚至看起来有点合理。(当然,我们很快就会用完字母,这就是Git使用那些大而难看的散列ID的原因。)下面是一个存储库的示例,其中只有一个
master
和八个提交,它们的散列ID是
a
H

A <-B <-C ... <-F <-G <-H   <--master
现在,两个分支都指向commit
H
。我们选择一家分行“开启”,并使用
git checkout
将我们的
HEAD
附加到该分行:

...--F--G--H   <-- master, develop (HEAD)
现在,真正聪明的事情发生了。现在Git将
I
的散列ID写入附加到的分支名称
头中:

...--F--G--H   <-- master
            \
             I   <-- develop (HEAD)
你的过滤器会改变你的作者信息。提交
A
成为新提交
A'

        D--E   <-- master
       /
A--B--C
       \
        F--G  <-- feature

A'   [in progress]
这会一直重复到
E
G

        D--E   <-- master
       /
A--B--C
       \
        F--G  <-- feature

        D'-E'  <-- (replacement for master)
       /
A'-B'-C'
       \
        F'-G'  <-- (replacement for feature)

D--E感谢您在@torek发布的内容丰富的帖子,有助于巩固我的理解。但我不明白这一点:“您现在只需对新存储库进行新的克隆,这是一个新项目,您永远不应该连接到旧项目:这两个项目不再兼容,提交也不能再从一个项目转移到另一个项目。”这不是GitHub的建议,也不是我所做的,至少从字面上说是这样。GitHub的process force推送临时repo,覆盖原始文件,在本地,它是同一个项目。原来的提交已经不存在了,新的工作是基于新版本的,但它是相同的回复。@enigment:我这里有我祖父的斧头。它只有两部分,一个铁制的斩头和一个木制的把手。我父亲在把手坏了的时候换了它,我去年换了它的头。我祖父的斧头没有留下任何零件。这把斧子真的是我祖父的斧子吗?回答那个问题
        D--E   <-- master
       /
A--B--C
       \
        F--G  <-- feature
        D--E   <-- master
       /
A--B--C
       \
        F--G  <-- feature

A'   [in progress]
        D--E   <-- master
       /
A--B--C
       \
        F--G  <-- feature

A'-B'   [in progress]
        D--E   <-- master
       /
A--B--C
       \
        F--G  <-- feature

        D'-E'  <-- (replacement for master)
       /
A'-B'-C'
       \
        F'-G'  <-- (replacement for feature)