我刚开始学习git并且这样做我开始阅读Git社区书,在本书中他们说SVN和CVS存储文件之间的差异,而git存储所有文件的快照.
但我并没有真正了解快照的含义.git是否真的复制了每个提交中的所有文件,因为这是我从他们的解释中理解的.
PS:如果有任何人有更好的学习git的来源我会很感激.
Git与大多数其他版本控制系统之间的主要区别之一是,其他人倾向于将提交存储为一系列增量 - 一次提交与下一次提交之间的更改集.这似乎是合乎逻辑的,因为它是存储提交的最小可能信息量.但是,提交历史记录越长,比较修订范围所需的计算就越多.
相比之下,Git 在每个版本中存储了整个项目的完整快照.这并没有使回购规模显着每个提交成长的原因是项目中的每个文件存储在Git的子目录中的文件,名为对其内容的哈希值.因此,如果内容未更改,则散列未更改,并且提交仅指向同一文件.还有其他优化.
所有这些对我来说都是有意义的,直到我偶然发现有关包文件的信息,Git定期将数据放入其中以节省空间:
为了节省空间,Git使用了packfile.这是一种格式,其中的Git只会保存在第二个文件已经改变,它的指针是类似文件的一部分.
这基本上不会回到存储增量吗?如果没有,它有什么不同?这如何避免Git遇到其他版本控制系统遇到的相同问题?
例如,Subversion使用增量,回滚50个版本意味着撤消50个差异,而使用Git,您可以获取适当的快照.除非git还在packfiles中存储50个差异...是否有一些机制说"在经过一些少量的增量后,我们将存储一个全新的快照",这样我们就不会堆积太大的变更集?Git还有什么可以避免增量的缺点?
据我所知,术语"分支"(用Git的说法)可能指的是相关但不同的东西:
但是,我已经看到这个术语过去常常是指三种可能的用法以外的东西(下面有更多细节).在Git上下文中,我的列表中缺少的"分支"一词是否还有其他有效和明确的用法?
使用Git大约一年后,我正在为CS学生准备一个简短的教程.我真的想要确定Git术语,以避免任何混淆.
当然,我现在已经使用Git分支了一段时间; 我很习惯使用它们并且发现Git分支模型很棒.但是,我仍然发现术语"分支"有问题且含糊不清,因为它似乎至少引用了两个不同的东西,具体取决于它所使用的上下文...有时甚至在同一个教程/手册中.
Pro Git书(3.1中 - 分支是什么),在显示下图后,

继续将分支定义为
只是一个指向其中一个提交的轻量级可移动指针.
据我所知,这也是Git手册页中"分支"的含义.
我对这个定义非常满意.我认为分支只是指向DAG中特定提交的引用,而分支的"提示提交"是该引用指向的提交.到现在为止还挺好.可是等等...
该Atlassian的Git的教程介绍分支如下:
分支代表独立的发展路线.
我猜他们的意思是一串提交.让我改进一下这个想法......唯一对我有意义的解释是术语"分支"也可以指存储库的提交DAG的子图,该提交DAG由所考虑的提示提交可到达的所有提交组成.
但是,Pro Git书籍也包含以下图表(参见3.4 - 分支工作流程),

这似乎与我的解释相矛盾,因为它似乎暗示只有提交C2- C5(不C1)属于develop分支,并且只提交C6- C7(不是C1- C5)属于topic分支.
我发现这种用法含糊不清,因为如果我在那个阶段绘制DAG,而不知道分支引用在过去指向的位置,并且没有任何假设三个分支之间的任何层次结构,我会得到的是

我还发现其他Git学习资源中的一些图表令人困惑.特别考虑以下内容(取自Lynda.com的介绍视频- Git Essential Training):

这里,尖端master是实际 534de(和HEAD指向master),但图中的"主"标签的位置是非常误导.在这种情况下,该标签应该描述的是我不清楚的......
编辑:我已经 …
foxtrot合并是一种合并,其中'origin/master'作为第二个(或更晚的)父级合并,如下所示:
提交'D'是foxtrot合并,因为'origin/master'是它的第二个父级.注意此时来自"origin/master"的第一父历史如何包含提交"B".
但是在我的git repo中,我需要所有涉及'origin/master'的合并来保持'origin/master'作为第一个父级.不幸的是,git在评估提交是否符合快进条件时并不关心父级.这会导致我的主分支上的第一个父历史记录有时会丢失曾经存在的提交(例如,输出"git log --first-parent").
以下是推送前面图表中提交"D"时发生的情况:
我怎样才能防止这种推动?推送foxtrot合并后,'origin/master'的第一父历史不再包含提交'B'!
显然没有提交或工作实际上丢失,只是在我的环境中我真的需要"git log --first-parent"作为一个稳定的提交累积记录 - 如果你愿意,一种"一次写入读 - 许多"(WORM)数据库.我有脚本和进程使用"git log --first-parent"来生成更改日志和发行说明,以及管理我的票证系统(JIRA)中的票证转换.Foxtrot合并破坏了我的脚本!
是否有某种预接收挂钩我可以安装在我的git存储库中以防止foxtrot合并被推送?
ps使用http://bit-booster.com/graph.html生成此stackoverflow问题中的提交图.
我正在与merge.conflictStyleset进行合并diff3.通常,这会插入由四(4)组字符分隔的三(3)个部分.
合并的Git文档清楚地解释了这些符号对于简单案例的含义(如下所述).
常规diff3:
Here are lines that are either unchanged from the common ancestor, or cleanly resolved because only one side changed.
<<<<<<< yours:sample.txt
Conflict resolution is hard;
let's go shopping.
|||||||
Conflict resolution is hard.
=======
Git makes conflict resolution easy.
>>>>>>> theirs:sample.txt
And here is another line that is cleanly resolved or unmodified.
Run Code Online (Sandbox Code Playgroud)
但是,我得到了一个更复杂的结果,有许多额外的行(见下文).我有一种感觉,这与我正在合并的提交的祖先中进行了大量合并这一事实有关,但我无法弄清楚额外的行是什么意思.我似乎也找不到这种行为的任何文档.
这是我得到的(编辑当然,以保护代码的身份).
(我试图合并的任何提交的代码中都没有冲突标记,所以这不是答案.)
<<<<<<< ours
||||||| base
<<<<<<< Temporary merge branch 1
||||||| merged common ancestors
if (sendRedirect(result)) …Run Code Online (Sandbox Code Playgroud) 从git merge文档中提取的递归合并策略的定义。
这只能使用3向合并算法解析两个磁头。当有一个以上的公共祖先可用于三路合并时,它将创建一个公共祖先的合并树,并将其用作三路合并的参考树。据报道,这样做可以减少合并冲突,而不会因对Linux 2.6内核开发历史记录中的实际合并提交进行测试而导致合并错误。此外,这可以检测和处理涉及重命名的合并。当拉或合并一个分支时,这是默认的合并策略。
递归策略可以采用以下选项:
如前所述,递归策略是默认策略,它使用3向递归合并算法(在此处和Wikipedia上进行了说明)。
我的理解是冲突的大块必须手动解决,并且通常以这种方式表示
<<<<<<<<<<<
developer 1's code here
============
developer 2's code here
>>>>>>>>>>>
Run Code Online (Sandbox Code Playgroud)
在我们的递归合并策略的选择进行了说明如下:
通过支持我们的版本,此选项可以强制自动解决冲突的大块。与另一棵树不冲突的更改会反映到合并结果中。对于二进制文件,全部内容都是从我们这边获取的。
这不应与我们的合并策略混淆,该策略甚至根本不看另一棵树包含的内容。它丢弃另一棵树所做的所有操作,声明我们的历史包含其中发生的所有事件。
现在假设我有两个分支Y和M的头,并且具有一个共同的基本祖先B,如下所示
当使用默认递归策略合并Y和M时,第30行将变为Print("hello");行,因为在第30行,Y表示从基本祖先开始的更改,而M则不是。但是如果我在M分支上并运行
git merge -s recursive -X ours Y
第30行会成为Print("bye");合并后的输出吗?
对于那些说这很明显的人,请注意我们的选项指出
通过支持我们的版本,此选项可以强制自动解决冲突的大块。
但是(据我了解)在第30行没有冲突的块。
为了完整起见,我还将提供他们的选项的文档:
这与我们的相反。
我们的策略文档如下:
这样可以解析任意数量的head,但是合并的结果树始终是当前分支head的树,有效地忽略了所有其他分支的所有更改。它旨在取代侧支的旧开发历史。请注意,这与递归合并策略的-Xours选项不同。
所以回到上面的例子,如果我跑了
git merge -s ours Y
在分支M上,很明显第30行将Print("bye");在合并的输出中。在这种情况下,为什么也没有 …
我正在使用git来跟踪我的LaTeX文档的更改.我倾向于将共同作者的反馈保留在一个单独的分支中,并在以后合并.到目前为止,事情似乎神奇地合并,但我想知道何时发生合并冲突,以便我可以在合并过程中获得一些真正的信任(我当然不希望文本出来时髦).
StackOverflow上有很多问题似乎都提出了同样的问题,但没有一个问题非常具体.例如,这个答案指定如果对同一个区域进行了更改就会发生冲突,但这让我想知道这些区域到底是什么.是仅仅对同一行进行了更改,还是考虑了某些上下文?