git branch,fork,fetch,merge,rebase和clone之间有什么区别?

问题描述 投票:487回答:5

我想了解Git中分支,分支和克隆之间的区别?

同样,当我做git fetch而不是git pull时,它意味着什么?

另外,与rebase相比,merge的意思是什么?

我怎样才能将各个提交自己压缩在一起?

他们是如何使用的,为什么使用它们以及它们代表什么?

GitHub如何计算?

git branch clone git-clone gitx
5个回答
359
投票

克隆只是存储库的副本。从表面上看,其结果相当于svn checkout,您可以从其他存储库下载源代码。集成VCS(如Subversion)和DVCS(如Git)之间的区别在于,在Git中,当您克隆时,实际上是在复制整个源存储库,包括所有历史记录和分支。您现在在您的计算机上有一个新的存储库,您进行的任何提交都会进入该存储库。在将这些提交推送到另一个存储库(或原始存储库)或直到有人从存储库提取提交(如果它是可公开访问的)之前,没有人会看到任何更改。

分支是存储库中的东西。从概念上讲,它代表了一个发展的线索。您通常有一个主分支,但您可能还有一个分支,您正在处理某些功能xyz,另一个用于修复bug abc。当您签出分支时,您所做的任何提交都将保留在该分支上,并且不会与其他分支共享,直到您将它们合并或将它们重新绑定到相关分支上。当然,对于分支来说,Git看起来有点奇怪,直到你看到分支实现的基础模型。而不是自己解释(我已经说得太多了,我已经说过了),我将链接到Git模型分支和提交的“计算机科学”解释,取自Git网站:

http://eagain.net/articles/git-for-computer-scientists/

叉子确实不是Git概念,它更像是一种政治/社会观念。也就是说,如果某些人对项目的运行方式不满意,他们可以将源代码与原始开发人员分开处理。这将被视为一个分叉。 Git使得分叉变得容易,因为每个人都有自己的源代码“主”副本,所以它就像切断与原始项目开发人员的联系一样简单,并且不需要从共享存储库导出历史记录,就像你可能与SVN一样。

编辑:因为我不知道像GitHub这样的网站使用的“fork”的现代定义,请查看我的评论以及我下面的Michael Durrant's answer以获取更多信息。


520
投票

Git

这个答案包括GitHub,因为很多人都对此问过。

本地存储库

Git(本地)有一个您提交文件的目录(.git),这是您的“本地存储库”。这与SVN等系统不同,您可以立即添加和提交到远程存储库。

Git通过保存整个文件来存储更改的文件的每个版本。它在这方面也与SVN不同,因为您可以访问任何单个版本而无需通过增量更改“重新创建”它。

Git根本没有“锁定”文件,因此避免了编辑的“独占锁定”功能(像pvcs这样的旧系统),所以即使离线也可以编辑所有文件。它实际上在拉取或提取/推送到远程存储库(如GitHub)期间将文件更改(在同一文件中!)合并在一起。您需要进行手动更改(实际编辑文件)的唯一时间是两次更改涉及相同的代码行。


分行

分支允许您保留主代码('主'分支),制作副本(新分支),然后在该新分支内工作。如果工作需要一段时间,或者master在获得分支后会获得大量更新,那么应该对主分支进行合并或重新定位(通常首选为更好的历史记录并且更容易解决冲突)。完成后,将分支中所做的更改合并到主存储库中。许多组织为每个工作使用分支,无论它是功能,错误还是杂项。其他组织仅使用分支进行主要更改,例如版本升级。

Fork:使用分支控制和管理分支,而使用fork,其他人控制接受代码。

从广义上讲,分支机构有两种主要方法。第一种方法是在主分支上保留大多数更改,只使用分支来处理较大和较长时间运行的事情,例如版本更改,您希望有两个分支可用于不同的需求。第二个是你基本上为每个功能请求,错误修复或杂项创建一个分支,然后手动决定何时实际将这些分支合并到主主分支。虽然这听起来很乏味,但这是一种常见的方法,也是我目前使用和推荐的方法,因为这使得主分支更清洁,而且它是我们提升到生产的主人,所以我们只需要通过变基和合并分支机构。

将分支'in'带入掌握的标准方法是做一个merge。分支机构也可以“重新定位”以“清理”历史。它不会影响当前状态,并且可以提供“更清洁”的历史记录。

基本上,这个想法是你从某一点(通常来自主人)分支。自从你分支以来,'master'本身已经从那个分支点向前推进了。如果您在分支中完成的所有更改都是针对当前状态的master进行的,并且具有所有最新更改,那么它将更“干净”(更容易解决问题并且历史记录将更容易理解)。因此,过程是:保存更改;获取'new'主服务器,然后再次应用(这是rebase部分)对此更改。请注意,与合并一样,rebase可能会导致您必须手动解决的冲突(即编辑和修复)。

需要注意的一条准则: 如果分支是本地的,你还没有把它推到远程,只有rebase! 这主要是因为变基可以改变其他人看到的可能包括他们自己的提交的历史。

Tracking branches

这些是名为origin/branch_name的分支(而不仅仅是branch_name)。当您将代码推送到远程存储库或从远程存储库中提取代码时,这实际上是发生这种情况的机制。例如,当你git push一个名为building_groups的分支时,你的分支首先进入origin/building_groups,然后进入远程存储库。同样,如果你执行git fetch building_groups,则检索到的文件将放在origin/building_groups分支中。然后,您可以选择将此分支合并到本地副本中。我们的做法是总是做一个git fetch和一个手动合并,而不仅仅是一个git pull(它一步完成上述两个步骤)。

Fetching new branches.

获得新分支:在克隆的初始阶段,您将拥有所有分支。但是,如果其他开发人员添加分支并将其推送到远程,则需要有一种方法来“了解”这些分支及其名称,以便能够在本地将其删除。这是通过git fetch完成的,它将使用跟踪分支(例如,origin/)将所有新的和更改的分支放入本地存储库。一旦fetched,可以git branch --remote列出跟踪分支和git checkout [branch]实际切换到任何给定的分支。

合并

合并是组合来自不同分支或来自同一分支的不同版本的代码更改的过程(例如,当本地分支和远程不同步时)。如果一个人在一个分支中开发了工作并且工作已经完成,准备好并经过测试,那么它就可以合并到master分支中。这是由git checkout master完成切换到master分支,然后git merge your_branch。合并将把所有不同的文件甚至不同的更改带到同一个文件中。这意味着它实际上将更改文件中的代码以合并所有更改。

当做checkoutmaster时,它还建议做一个git pull origin master,以便将最新版本的远程主机合并到你的本地主机。如果遥控主人改变了,即moved forward,你会看到反映在那个git pull期间的信息。如果是这种情况(主人更改),建议您使用git checkout your_branch然后rebase掌握它,以便您的更改实际上在'新'主人之上'重播'。然后,您将继续获取最新的主数据,如下一段所示。

如果没有冲突,那么master将添加新的更改。如果存在冲突,这意味着相同的文件在类似的代码行中发生了更改,无法自动合并。在这种情况下,git merge new_branch将报告存在要解决的冲突。您可以通过编辑文件(将对其进行更改)来解决这些问题,选择所需的更改,从字面上删除不需要的更改行,然后保存文件。这些更改标有========<<<<<<<<等分隔符。

一旦你解决了任何冲突,你将再次git addgit commit这些更改继续合并(你将在这个过程中从git获得反馈来指导你)。

当这个过程不能正常工作时,你会发现git merge --abort非常便于重置。

交互式变基和压缩/重新排序/删除提交

如果您已经完成了许多小步骤的工作,例如,您每天都将代码设置为“正在进行中”,那么您可能希望将这些许多小型提交“压缩”为几个较大的提交。当您想与同事进行代码审查时,这可能特别有用。你不想重放你所采取的所有“步骤”(通过提交),你只想说这是我在一次提交中对这项工作的所有更改的最终结果(差异)。

在考虑是否这样做时要评估的关键因素是多次提交是否多次针对同一个文件或文件(在这种情况下更好地压缩提交)。这是通过交互式变基工具完成的。这个工具可以让你压缩提交,删除提交,重写消息等。例如,git rebase -i HEAD~10(注意:这是一个~,而不是-)会显示以下内容:

interactive rebasing in Git

但要小心,并小心翼翼地使用这个工具。一次进行一次压缩/删除/重新排序,退出并保存该提交,然后重新输入该工具。如果提交不连续,您可以重新排序(然后根据需要压缩)。你实际上也可以在这里删除提交,但是当你这样做时,你真的需要确定你在做什么!

福克斯

Git存储库中有两种主要的协作方法。上面详细介绍的第一个是直接通过人们拉/推的分支。这些协作者的SSH密钥已在远程存储库中注册。这将让他们直接推送到该存储库。缺点是你必须维护用户列表。另一种方法 - 分叉 - 允许任何人“分叉”存储库,基本上在他们自己的Git存储库帐户中制作本地副本。然后他们可以进行更改,并在完成后发送一个“拉取请求”(实际上它更多的是来自他们的“推送”以及对实际存储库维护者的“拉动”请求)以接受代码。

第二种方法使用分叉,不需要有人维护存储库的用户列表。


GitHub

GitHub(远程存储库)是一个远程源,如果您已经(或被添加到)这样的存储库,您通常会将这些已提交的更改推送到这些源,因此本地和远程实际上非常不同。另一种思考远程存储库的方法是它是一个位于远程服务器上的.git目录结构。

当您'fork'时 - 在GitHub Web浏览器GUI中,您可以单击此按钮 - 您在GitHub帐户中创建代码的副本('clone')。第一次执行此操作时可能会有点微妙,因此请务必确保查看其下方列出的代码库的存储库 - 原始所有者或“分叉”和您,例如,如下所示:

获得本地副本后,您可以根据需要进行更改(通过拉动并将其推送到本地计算机)。当你完成后,你向原始存储库所有者/管理员提交一个“拉取请求”(听起来很奇特,但实际上你只是点击这个:),然后他们“拉”进去。

对于一起处理代码的团队来说,更常见的是“克隆”存储库(单击存储库主屏幕上的“复制”图标)。然后,本地键入git clone和粘贴。这将在本地设置你,你也可以推送到(共享)GitHub位置。

克隆

如GitHub一节所示,克隆是存储库的副本。当您拥有远程存储库时,可以针对其URL发出git clone命令,然后最终获得存储库的本地副本或克隆。这个克隆包含所有内容,文件,主分支,其他分支,所有现有提交,整个shebang。您正在添加和提交此克隆,然后远程存储库本身就是您推送这些提交的内容。正是这种本地/远程概念使得Git(以及与Mercurial类似的系统)成为DVCS(分布式版本控制系统),而不是更传统的CVS(代码版本控制系统),如SVN,PVCS,CVS等。您直接提交到远程存储库。

可视化

可以看到核心概念的可视化 http://marklodato.github.com/visual-git-guide/index-en.htmlhttp://ndpsoftware.com/git-cheatsheet.html#loc=index

如果你想要直观地显示变化是如何工作的,你就不能用我称之为“地铁地图”(特别是伦敦地铁)的GUI击败可视化工具gitggitx for macOS),非常适合展示谁做了什么,事情如何变化,分歧和合并等等

您还可以使用它来添加,提交和管理您的更改!

Image of gitg/gitx interface

尽管gitg / gitx相当小,但GUI工具的数量仍在不断扩大。许多Mac用户使用brotherbard的gitx分支,对于Linux,一个很好的选择是smart-git,具有直观而强大的界面:

Image of smart-git GUI

请注意,即使使用GUI工具,您也可能会在命令行执行大量命令。

为此,我在~/.bash_aliases文件中有以下别名(从我的~/.bashrc文件中为每个终端会话调用):

# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '

我在我的~/.gitconfig文件中有以下“git别名” - 为什么有这些? 所以分支完成(使用TAB键)有效!

所以这些是:

[alias]
  co = checkout
  cob = checkout -b

用法示例:git co [branch]

GUI学习工具

您可能会发现qazxsw poi在学习一些基本概念时很有用。屏幕截图:qazxsw poi 视频:qazxsw poi

最后,7个关键的救生员!

  1. 你进行更改,添加和提交它们(但不要推)然后哦!你意识到自己掌握了! https://learngitbranching.js.org/
  2. 你在本地分支机构工作时搞砸了一些文件,只想回到你上次做enter image description here时的情况: https://youtu.be/23JqqcLPss0
  3. 你开始在本地进行更改,你编辑了六个文件然后,哦,废话,你仍然在主(或另一个)分支: git reset [filename(s)] git checkout -b [name_for_a_new_branch] git add [file(s)] git commit -m "A useful message" Voila! You've moved that 'master' commit to its own branch !
  4. 你弄乱了当前分支中的一个特定文件,并希望基本上“重置”该文件(丢失更改),以便它是从上次从远程存储库中提取它时的方式: git pull 这实际上会重置文件(就像许多Git命令一样,它没有很好地命名它在这里做什么)。
  5. 你在本地进行了一些更改,你想确保在做git reset --hard origin/master # You will need to be comfortable doing this! git checkout -b new_branch_name # just create a new branch git add . # add the changes files git commit -m"your message" # and commit them 时不要丢失它们:我经常制作整个项目的手动副本(git checkout your/directories/filename ),当我不确定我是否会搞砸Git或失去重要的变化。
  6. 你正在变形,但事情搞砸了: git reset
  7. 将您的Git分支添加到rebase提示符(请参阅cp -r ../my_project ~/),例如 git rebase --abort # To abandon interactive rebase and merge issues 分支是PS1

142
投票

以下是奥利弗·斯蒂尔(Oliver Steele)关于如何将它们组合在一起的图像:


7
投票

叉子比克隆 - 两个词都意味着复制

请看这个https://unix.stackexchange.com/a/127800/10043(最初来自Image of prompt)。

selenium_rspec_conversion

叉子

  • 复制到您的远程仓库(云),将其链接到Joe的
  • 然后,您可以复制到本地仓库和F *%$ - up
  • 完成后,您可以回到遥控器
  • 然后,您可以通过单击pull-request询问Joe是否要在其项目中使用它

克隆

  • 复制到您当地的仓库(硬盘)

6
投票

只是添加到其他人,一个特定于分叉的注释。

很高兴认识到,从技术上来说,克隆回购和分销回购是一回事。做:

diagram.

你可以在后面敲击自己---你刚刚分开了一些其他的回购。

作为VCS,Git实际上就是这样 克隆 分叉。除了使用远程用户界面(例如cgit)“只是浏览”之外,与git repo几乎没有关系, 分叉 在某些时候克隆回购。

然而,

  • 当有人说我分叉回购X时,他们意味着他们在其他地方创建了回购的克隆,意图将其暴露给其他人,例如展示一些实验,或者应用不同的访问控制机制(例如,允许没有人Github访问但与公司内部帐户进行协作)。 事实是:repo很可能是用http://www.dataschool.io/content/images/2014/Mar/github1.png之外的其他命令创建的,它最有可能在服务器上的某个地方托管,而不是某人的笔记本电脑,而且很可能有一些略有不同的格式(它是一个“裸仓”,即没有工作树)都是技术细节。 事实上它很可能包含不同的分支,标签或提交集合,这很可能是他们首先做到这一点的原因。 (点击“fork”时Github会做什么,只是克隆加糖:它为您克隆回购,将它放在您的帐户下,记录“分叉”某处,添加名为“上游”的远程,最重要的是,播放好动画。)
  • 当有人说我克隆了回购X时,他们意味着他们已经在他们的笔记本电脑或台式机上本地创建了一个repo克隆,有意研究它,玩它,为它做贡献,或者从它的源代码构建一些东西。

Git的魅力在于它使这一切完美契合:所有这些回购共享共同的部分 块 提交链,这样就可以安全地(参见下面的注释)在你认为合适的所有这些回购之间来回合并变化。


注意:“安全”,只要您不重写链的公共部分,并且只要更改不冲突。

© www.soinside.com 2019 - 2024. All rights reserved.