无法理解Git分支、合并和变基

9
我知道这个帖子说rebase适用于团队成员进行小的更改,而合并适用于大的更改。
我在以下目录结构中保留了三个团队成员的三个Git,我们都有相同的初始代码:
project 
      | - I
      | - myTeamMate1
      | - myTeamMate2

这些分支不在同一个Git中,这意味着我不能使用rebase和merge。我已经使用vimdiff来同步团队成员之间的更改,但这很耗时间。

我曾试图创建以下目录结构,使得所有分支都在一个Git下,但未成功:

project
      | - I - myTeamMate1 - myTeamMate2

然而,我为自己和我的队友运行了克隆命令:

git clone <url>

在为我的队友运行第二次克隆之后,我收到了错误消息。

fatal: destination path 'dotFiles' already exists and is not an empty directory.

如果我和另外两个人组成一个团队,应该使用哪种目录结构,这样我可以使用 rebasemerge 命令?

4个回答

10

以下是对Samuel回答的补充思路。

  • 与SVN不同,Git中分支和目录完全无关:拥有3个分支(每个团队成员一个)并不意味着有3个目录。虽然这不是你问题的意思(因为你的目录实际上是3个Git存储库的根目录),但我还是希望明确提及;)

  • 由于Git是分布式版本控制系统,3个存储库可以位于任何位置(而不是在同一台计算机上的3个目录)。如果它们可以通过UNC路径(\\desktop\path\to\repo)访问,则可以将它们指定为远程存储库。

  • Git clone命令确实允许获取远程分支的引用,但不会创建跟踪本地分支,以便获取同事的工作。Ruby模块“remote branches”可以提供帮助。

  • 谨慎使用变基操作,因为它会重写当前分支的SHA-1(因为你要在另一个分支上重播你的提交记录):如果你的团队成员基于你的分支进行合并,他们每次都必须合并所有已经合并过的提交!
    在这种情况下最好有2个分支:

    • 一个工作分支,用于开发和变基操作(以整合同事的工作,尽管这个操作也可以在自己的分支上完成)
    • 一个发布公共分支,只合并稳定的工作,并且其他远程存储库可以将其用作合并的源。

我接受这个答案,因为它足够“深入”。不过,请查看Samuel的回答以及我的关于解决问题的具体示例的回答。--感谢您的回答! - Léo Léopold Hertz 준영
@VonC:Ruby模块“远程分支”在你的Ubuntu Jaunty上能用吗? 在安装了rubygems和README文件中列出的所有依赖项后,它会显示“grb命令未找到”。 - Léo Léopold Hertz 준영
@Masi,是的应该可以(虽然没有直接测试过):sudo gem install git_remote_branch --include-dependencies 可以做到这一点,前提是你的 $PATH 引用了 Ruby bin 目录中的脚本。 - VonC
@Benjol:感谢你的编辑,我应该注意拼写错误了,但我还不够警觉以避免它们... - VonC

5

代码示例

要跟踪一个远程分支:

git remote add -t master Hnr git://github.com/userName/files.git

这并不会下载你的分支。它只是编辑文件.git/config,并添加一些行,告诉Git如何在哪里以及如何远程获取数据。
要获取你的团队成员的分支,请运行:
git fetch Hnr

要查看您是否真正拥有团队成员的分支,请运行

git branch -a

或者只查看您朋友的分支

git branch -r

最初,我对上述两个命令感到困惑,因为我不知道它们的作用。这让我尝试其他不必要的命令来获取分支。

第二种获取朋友代码分支的方法

然而,请注意,您可以使用git-clone将朋友的代码复制到另一个目录,如下所示:

git clone UrlAtGithub

然后,你可以像上面那样使用Git-remote,在你的Git仓库中创建一个分支:

git remote add master Hnr PATH/ToYourFriendRepo.git

结论:你可以使用两种方式来获取你的队友的分支,一种是通过git-clone,另一种则不需要。这两种方式都需要使用git remote add。后者的优点似乎在于你需要运行少一个命令。前者则可以将你的队友整个仓库复制到你的硬盘上。
请参阅Git手册以了解如何更新远程分支。注意,远程分支可以在你的计算机上,不一定要在远程计算机上。你的分支也可以是远程分支,但这会限制你的工作流程。
接下来,你可能想将你朋友的特定文件合并到你的分支中。在这种情况下,只需知道你朋友提交的前5个字母即可合并文件。
我不确定以下操作该怎么做:你需要运行例如:
git merge 76a32

您可能会得到以下输出。
CONFLICT (add/add): Merge conflict in shells/externalPrograms
Auto-merging shells/smallApps/extract
CONFLICT (add/add): Merge conflict in shells/smallApps/extract
Auto-merging shells/smallApps/extract~
CONFLICT (add/add): Merge conflict in shells/smallApps/extract~
Automatic merge failed; fix conflicts and then commit the result.

在这种情况下,你的文件与你朋友的文件有很大不同,Git 无法决定使用哪个文件。你需要运行以下命令:
git rebase

而且你会得到:
shells/smallApps/extract: needs merge
shells/smallApps/extract~: needs merge
cannot rebase: you have unstaged changes

练习1: 但是,我现在卡住了,因为我的tig不显示我的Git树中朋友的提交。 如何将您朋友的提交76a32添加到您的Git树,而该分支位于您的Git中?


您现在可能已经解决了问题。问题在于我忽略了解决Git提醒我有关冲突的问题。Google再次在官方Git网站上拯救了这一天:

如果存在冲突-例如, 如果同一文件在远程分支和本地分支中以两种不同的方式进行修改-那么你会 得到警告-

下一个问题是清理问题部分并重新合并。 您会在您的问题文件中看到类似以下内容-玩得开心!(我终于遇到了真正的问题;)

alt text http://dl.getdropbox.com/u/175564/exampleGitProblemSolving.png


在Mac的FileMerge中比较和合并dotFiles的问题

我需要更新我的Git,因为只有最新的Git才有difftool命令。您可以在线程中找到解决方案。

Difftool允许您从终端启动FileMerge中的dotFiles。您无法在GUI中访问它们。它的工作方式如下:

git difftool master:README dev:README

在添加新的远程账户后,Github账户出现问题

可能是您的Github账户在.git/config文件中丢失了。如果是这种情况,您需要运行以下代码:

git remote add -f YourUserName UrlIn@form.git

您可能会注意到,您无法正常进行 git-push 操作。

git push origin master

您可能会收到以下错误消息:
fatal: 'origin' does not appear to be a git repository
fatal: The remote end hung up unexpectedly

您也可以尝试以下命令来解决问题。

git push Masi master

所有3个Masi、master和origin的2个排列组合都没有起作用。

练习2: 如果你的远程列表中有一个队友,你该如何提交到你的github账户?

Origin是你实际的外部git-repo的简称,例如在Github上。你的变量origin的内容可能已被另一个远程repo替换。在这种情况下,我建议你创建一个新变量:

git remote add github git@github.com:myLogin/myProject.git

请注意,您可以在 github 的位置使用 origin2。Origin 只是命名存储库的约定。
然后,您只需运行:
git push github master

如果你的ssh-key中有密码,可能会出现权限被拒绝的警告。如果确实出现了这种情况,请参考这篇文章


你的回答中有一些很好的观点,谢谢你的反馈。+1 - VonC
1
注意:git merge或git rebase可能会导致冲突,如此处所述(https://dev59.com/qHRB5IYBdhLWcg3w9Lvn)。 您需要使用良好的diff工具解决这些合并冲突:更多详细信息请参见(https://dev59.com/fXRA5IYBdhLWcg3wsgFP) - VonC
@VonC:谢谢你的建议!--我目前正在努力让我的Mac程序可以直接在Zsh中启动。我注意到Mac默认有FileMerge程序。它似乎与你在答案中提到的程序类似。 - Léo Léopold Hertz 준영

5

事实上,它们不在与你相同的 git 中并不会限制你。Git 是分布式的,这意味着你可以在这些仓库之间进行获取(fetch),合并(merge),变基(rebase)等操作。

查看 git remote --help 以了解如何在你的仓库中命名你的队友的仓库,以便你可以轻松地导入(import)他们的更改,对其进行变基(rebase)或执行合并(merges)。没有必要更改你的目录结构,你的目录结构完全可用。


远程命令并不意味着不同的 Git 必须在不同的计算机上。它只是意味着你有许多 Git 来处理你的项目。 - Léo Léopold Hertz 준영
没错。只要仓库可以被访问,无论是本地还是远程,它就是远程仓库。嗯,你甚至可以将自己的仓库指定为远程仓库,但使用范围非常有限。 - Samuel Tardieu

4
说实话,我本来想打一份漂亮、长而详细的回复......但我发现这篇文章 http://excess.org/article/2008/07/ogre-git-tutorial/ 已经比我能写的更好了。它讲解了不同分支、远程和合并的使用方法,并且还有屏幕录像,所以花一个小时,拿杯咖啡来欣赏整个讲座吧。
特别针对你的问题:你不应该使用目录设置。Git 不会处理目录中的分支,就像 SVN 处理分支文件夹那样。在 Git 中,分支是完全不同的东西。虽然你可能不需要设立一个中心仓库(我建议这么做),但你应该设立一个单独的分支,每个人都将他们的最终干净的工作提交到那里。
我的例子仓库之一,在Wikimedia Commons上有一张截图。在我的例子中,“bartender”只提交 tar 块的代码,因此我必须自己导入它以管理它。“master”(这里仅显示为 remotes/elf/master)是一个公共 svn 仓库,我导入并基于其做出更改。“autocracy”是代码的基准线,“private”中保存了一个我想管理但从未发布的密码配置文件。检查一下“private”上的时间戳,你会发现它们与下面的分支不对齐。这是因为我将该分支 重新定位到“autocracy”而不是合并
你会注意到两个远程引用:elf 和 bard。这些都是我的两台主机上托管软件的远程机器。我可以随意推送和拉取我的分支到那里。在你的情况下,你会有其他开发人员远程仓库,并且他们会修改自己的分支。看完教程后,你会更好地了解它的工作原理。祝你好运 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接