Git-防止在合并时添加开发目录

Git-防止在合并时添加开发目录,git,git-merge,Git,Git Merge,我是一名程序员,更熟悉高级编程语言,如C#或Python,但我最近开始深入研究Git的复杂性。上下文:我正在开发一个游戏,我有一个development分支,它有一个特定的'development'目录,为了保持master干净,不会在合并中推送到master 我来到了一个几乎能胜任这项工作的地方;但是,这种方法虽然不会将更改提交到目录,仍然会在主节点分支上创建它,这意味着每次合并后,我仍然需要返回并手动删除文件 我正在设置一个别名git publish来自动执行此任务,为了完整起见,我将在这里

我是一名程序员,更熟悉高级编程语言,如C#或Python,但我最近开始深入研究Git的复杂性。上下文:我正在开发一个游戏,我有一个
development
分支,它有一个特定的
'development'
目录,为了保持
master
干净,不会在合并中推送到
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"

我想知道,有没有什么办法可以阻止
资产/开发/
主机上创建?

旁注:摆弄
.gitignore
不会有帮助,因为
.gitignore
的本质不是真正的“要忽略的文件”,而是“用于抑制某些投诉的文件,和/或在某些情况下可以随意销毁的文件”。(这并不是说您不应该出于其他原因调整
.gitignore
,只是这无助于解决此合并问题,因为您确实希望在开发分支中对这些文件进行版本控制。)

您现有的解决方案(以及可能改进的方法) 一个技巧基本上就是你现在正在做的:进行合并(使用
--no commit
),然后去掉你不想要的东西

剥离步骤如下所示:

git reset -- Assets/Development/
这使用了
--mixed
(默认,并在提供路径时强制您)形式的
git reset
,它设置(或“reset”,实际上)索引以匹配指定路径的指定树。这里的路径是
Assests/Development/
,即该子目录中的所有内容。指定的树没有指定,因此它默认为
HEAD
,或者更确切地说,
HEAD
的树是当前分支上的当前提交,这当然是
master
,因为我们刚刚选中了它那就是:而且
master
根本不包含
Assets/Development/
,因此重新设置的索引现在不再包含该子树

简言之,由于
Assets/Development/
不在
HEAD
中,这会撤消
git merge
Assets/Development
中的所有内容所做的
git add
操作。问题是,虽然这会从索引中删除条目,但会将它们留在工作树中

人们可能会尝试
git reset--hard--Assets/Development/
,但git不会这么做:在提供路径时,不能指定重置模式。不过,这还剩下三个明显的选项:

  • 添加
    rm-r资产/开发
    (就在
    git重置
    之前或之后,甚至在
    提交
    步骤之后)

    这将删除这些文件,这样,当它们从索引和工作树中消失后,您就可以提交并完成它们了

  • 使用
    git-rm-rf资产/开发/
    (代替
    git重置

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

  • 提交后使用
    git clean
    。这可能会超出您的需要

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

更多关于合并 当运行
git merge
时,git首先找到合并基

合并基数被定义为LowestCommonAncestor(LCA)在图中两个节点之间的提交图中。在本例中,这两个节点是您当前的提交,分支
master
的提示,以及您提交给
git merge
,在本例中,这是分支
开发
的提示提交。LCA的定义需要一点图论,但不严格地说,这是两个提交历史记录上的“最近”提交

为了了解这是如何工作的,它有助于绘制提交图的一部分。这里我们将
master
development
作为两个分支提示,两个分支结构(提交链)最终连接在一起:

... <- o <- * <- o <- ... <- o     <-- master
             \
              o <- o <- ... <- o   <-- development
现在您继续在
development
上开发,进行更多新的提交。让我们用
o
替换
*
,因为它不再是特例

...--o--o--o-...-o---o       <-- master
         \          /
          o--o-...-o--o--o   <-- development
现在标记为
*
的节点可以从
主节点(通过向下和向左跟随第二个父节点)和
开发节点(通过向左跟随链)访问。它是最近的此类节点,因此是合并基础

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

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

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/
中添加了新文件,merge将很高兴地将它们添加到您即将进行的提交中,因此您确实需要
--no commit
来避免添加任何此类文件


如果需要,您可以再次使用
git rm-rf
抛出任何冲突和/或添加的文件。

为什么不能将其放入.gitignore?为什么不能将文件夹放在包含存储库的目录之外,
...--o--o--o-...-o---o       <-- master
         \          /
          o--o-...-*--o--o   <-- 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.