经过多年的svn使用后,我一直在尝试Git和Github。我似乎已经掌握了基础知识,但有一项令我困惑。
UserA对FileA进行了更改并推送到远程服务器 (GitHub)
UserB对FileB进行了更改。他先从远程拉出来 服务器,然后将其更改推送到FileB到远程服务器
GitHub提交历史记录显示来自UserA的推送和来自UserB的推送
但是,UserB的提交历史记录中还有一个名为“https://github.com/xxx/yyy”的“合并分支”主数据的附加条目。在Github中查看diff显示这是UserA对FileA所做的更改的精确复制
为什么显示这个副本 - 从UserA到FileA的推送和Merge分支主条目都是相同的...第二个对我来说似乎是多余的。
答案 0 :(得分:68)
存储在git中的每个版本(“commit”)构成了图形的一部分,并且根据该图形来考虑你在git中所做的事情通常很有帮助。
当UserA开始时,假设我们只创建了两个提交,我们称之为P
和Q
:
P--Q (master)
然后,他修改FileA,更改的阶段并创建表示源代码的新状态的提交 - 假设提交被称为R
。这有一个父项,即提交Q
:
P--Q--R (master)
成功推送后,GitHub存储库的提交图看起来是一样的。
UserB以相同的历史开头:
P--Q (master)
...但是创建了一个不同的提交,比如名为S
,它有修改后的FileB版本:
P--Q--S (master)
UserB尝试将其推送到GitHub,但推送被拒绝 - 除非您“强行”推送,否则不允许更新远程分支,除非您推送的版本包含该远程的所有历史记录科。所以,UserB来自GitHub。拉实际上包括两个步骤,取和合并。提取更新origin/master
,类似于远程master
的远程分支origin
的状态缓存。 (这是“远程跟踪分支”的示例。)
P--Q--S (master)
\
R (origin/master)
此图表中的历史记录有所不同,因此合并会尝试通过创建合并提交(例如M
)来统一这两个历史记录,该合并提交同时包含S
和R
作为父项,并希望代表两个分支的变化:
P--Q--S--M (master)
\ /
\ /
R (origin/master)
当GitHub显示一个表示提交引入的更改的diff时,在使用一个父提交的情况下它很简单 - 它只能从该版本执行diff。但是,对于M
等具有多个父级的提交,必须选择父级来显示差异。这就解释了为什么合并提交M
显示的差异似乎与S
或R
之一显示的差异相同。 git中的提交是由源树的确切状态定义的,而不是使树进入该状态的更改。