Git - 阻止在合并

时间:2016-04-14 16:26:06

标签: git git-merge

我是一名熟悉高级编程语言(如C#或Python)的程序员,但我最近开始深入研究Git的复杂性。上下文:我正在开发一个游戏,我有一个development分支,其中包含一个特定的'Development'目录,为了保持master,它不会被合并到master。 1}}干净。

我来到this answer几乎完成了工作;但是,这个方法,虽然它不会提交对目录的更改,仍然会在master分支上创建它,这意味着每次合并后,我仍然需要返回并手动删除文件。

我正在设置一个别名git publish来自动执行此任务,我将在此处发布完整性:

[alias]
    publish = "!f(){ git checkout master \
        && git merge --no-commit --no-ff development \
        && git reset -- Assets/Development/ \
        && git commit \
        && git push; };f"

我想知道,有什么方法可以阻止在Assets/Development/上创建master吗?

1 个答案:

答案 0 :(得分:1)

旁注:由于.gitignore的性质,.gitignore无法摆弄,因为.gitignore不是真的"要忽略的文件",而是&# 34;在某些情况下压制某些抱怨和/或随意销毁的文件" (这并不意味着您不应该因为其他原因而调整--no-commit,只是因为它确实希望这些文件版本化在开发部门。)

您现有的解决方法(以及可能改进它的方法)

一个技巧基本上就是你现在正在做的事情:进行合并(使用git reset -- Assets/Development/ ),然后删除你不想要的东西。

剥离步骤是这样的:

--mixed

这使用git reset(默认情况下,并在给出路径时强制给你)形式Assests/Development/,它设置(或"重置",真的)索引以匹配指定路径的指定树。这里的路径是HEAD,即该子目录中的所有内容。指定的树没有指定 - 因此它默认为HEAD,或者更确切地说是HEAD的树。 master是当前分支的当前提交,当然是master,因为我们刚刚检查过;并且Assets/Development/根本不包含Assets/Development/,因此重新设置的索引现在不再具有该子树。

简而言之,因为HEAD不在git add,所以这会撤消git mergeAssets/Development中所有内容所做的git reset --hard -- Assets/Development/。问题是虽然这会删除索引中的条目,但它会将它们留在工作树中。

有人可能会尝试rm -r Assets/Development,但是git不会这样做:在提供路径时无法指定重置模式。但是,这留下了三个更明显的选择:

  • 添加git reset(在commit之前或之后,或甚至在git rm -rf Assets/Development/步骤之后)

    这会删除文件,因此当它们从索引和工作树中删除时,您可以提交并完成。

  • 使用git reset(代替git clean

    这将删除索引条目删除工作树文件(和目录),因此您可以提交并完成。

  • 提交后使用git merge <commit>。这可能比你想做的更多。

主要的是,你可能只需要做一次,而不是重复。这取决于你在此过程中所做的改变。

有关合并的更多信息

当你运行master时,git首先找到合并基础

合并基础在图表中两个节点之间的提交图中定义为 L owest C ommon A ncestor(LCA) 。这两个节点是您当前的提交 - 在这种情况下是分支git merge的提示 - 以及您对development的提交,在这种情况下是分支master的提示。 LCA的定义需要一点图论,但从宽松的角度讲,它是最近的&#34;提交在两个提交历史记录上。

要了解其工作原理,可以绘制部分提交图。在这里,我们将development... <- o <- * <- o <- ... <- o <-- master \ o <- o <- ... <- o <-- development 作为两个分支提示,两个分支结构(提交链)最终连接起来:

*

标记为development的提交是合并基础:它是master*重新加入的点,并且提交merge并且每个早期提交都在两个分支,而不仅仅是一个分支。

此时*所做的是生成两个差异:一个从master到当前提交的提示(*上的提示提交),另一个来自{{ 1}}到另一个,目标,提交(development的提示)。

master中,您有*后的一些(可能不是太多)更改,而在development中您有一些更改,包括添加Assets/Development/

merge命令组合了这些更改,包括添加不需要的目录。完成所有操作后,git会进行新的提交(--no-ff步骤保证这一点;如果合并基础提交*master的提示,这不是我们绘制的但可能在第一次合并时,git会尝试快速执行标签而不是进行实际合并。

结果是一个现在看起来更像是这样的图形(我将停止在左箭头中绘图,只要知道历史向左移动,即稍后提交指回早期的箭头):

...--o--*--o-...-o---o   <-- master
         \          /
          o--o-...-o     <-- development

现在,您继续在development上开发,进行更多新提交。我们将*替换为o,因为它不再是特殊情况。

...--o--o--o-...-o---o       <-- master
         \          /
          o--o-...-o--o--o   <-- development

并且在某些时候您决定再次合并,因此您检查master并告诉git merge找到development的(新)提示并计算合并基数。

合并基础是(并且有点松散),两个分支上的第一个提交。让我们找到它:它和以前一样吗?从masterdevelopment的提示开始,从每个着色节点向后工作,使用两种不同的颜色。一旦节点获得两种颜色,这就是共同的祖先。最靠近提示是&#34;最低&#34;,即合并基础。

我无法画出颜色,但如果你自己做这个练习,你会发现它是这个节点:

...--o--o--o-...-o---o       <-- master
         \          /
          o--o-...-*--o--o   <-- development

现在标记为*的节点可以从master(通过跟随第二个父级左下)和development(通过链左侧)到达。它是最接近的节点,因此它是合并基础。

Git现在将合并基础*与两个提示区分开来。如果对master的提示进行任何更改(基本上只有从先前的合并基础和o的新提示之间的master节点中获取的任何内容)应该很少,以及自上次合并以来您对development分支所做的更改。

如果这些更改影响Assets/Development中的现有文件,则这些更改将导致合并冲突:

CONFLICT (modify/delete): Assets/Development/foo deleted in HEAD
 and modified in development. Version development of
 Assets/Development/foo left in tree.
Automatic merge failed; fix conflicts and then commit the result.

请注意,您不需要--no-commit

如果这些更改在Assets/Development/中添加 new 文件,另一方面,merge会很乐意将它们添加到您即将进行的提交中,因此您需要{{1}避免添加任何此类文件。

如有必要,您可以再次使用--no-commit来删除任何冲突和/或添加的文件。