Git 如何从合并中排除文件?

Git 如何从合并中排除文件?,git,merge,Git,Merge,我刚开始关注git,目前正在考虑合并。假设我有一个主分支,我创建了一个名为child的分支。我在childbranch上工作并更改了一些文件。现在我想将此子分支合并到主分支中: git merge child 但是,在子分支中(也在主分支中)有一些文件我不想合并。如何将我的更改从子项合并到主项中,但从子项中排除特定文件?简短的回答很简单:否 长答案要复杂得多,但也相当于“不”。本质上,在某些情况下,您可以让Git相信,如果合并双方都有更改,那么更改总是冲突的。请看一个相关的问题(虽然我真正要说

我刚开始关注git,目前正在考虑合并。假设我有一个主分支,我创建了一个名为child的分支。我在childbranch上工作并更改了一些文件。现在我想将此子分支合并到主分支中:

git merge child

但是,在子分支中(也在主分支中)有一些文件我不想合并。如何将我的更改从子项合并到主项中,但从子项中排除特定文件?

简短的回答很简单:否

长答案要复杂得多,但也相当于“不”。本质上,在某些情况下,您可以让Git相信,如果合并双方都有更改,那么更改总是冲突的。请看一个相关的问题(虽然我真正要说的是,您可以将文件标记为二进制文件,或者设置特殊的合并驱动程序,但即使要达到这一点,您还需要了解很多背景知识)

如果要避免使用某些文件,可以使用
--no commit
运行
git merge

$ git status
On branch master
nothing to commit, working directory clean
$ git checkout -b sidebranch
... lots of coding, git committing, etc
$ git checkout master
... more coding and committing, etc.,
    or various merges of other branches,
    so that master and sidebranch are
    actually divergent (if they are
    not, note that merge would
    normally do a "fast forward" here)
$ git merge --no-commit sidebranch
在这一点上,Git将使用我在链接答案中描述的过程进行合并(通过做两个diff,然后组合这两个diff)。但即使成功,它也不会自动提交结果合并

这意味着您现在可以执行以下操作:

$ git rm path/to/ickyfile
    # we don't want this file, it's icky!
和/或:

$ git checkout --ours -- path/to/foo; git add path/to/foo
    # we want the current (master) version of this file,
    # ignoring all the changes made in the side branch
甚至像这样的东西(但不要:结果有时被称为“邪恶合并”):

$vim路径/至/bar
$git添加路径/到/bar
一旦你完成了让糟糕的事情发生在一个好的合并中:-)你就可以运行
git commit
来完成合并

一般来说,如果您发现需要这样做,您可能使用了错误的工具。尤其是,人们通常使用配置文件执行上述操作,而“正确”的做法是首先不要将这些文件放在Git(或任何版本控制系统)中


(取而代之的是,在VCS中放置一个示例配置文件。而不是
prog.conf
,而是添加并提交
prog.conf.example
。将
prog.conf
放置在
.gitignore
中。如果需要,您的安装/初始化代码可以将示例配置复制到位,以用于新用户设置。)

如果您犹豫合并的原因是您将遇到合并冲突,我认为您不应该这样做。 合并冲突解决,虽然是一项很难学习的任务,但您可以从中受益匪浅

但是,如果您现在不想这样做,或者如果您的问题是其他问题,我可以想出一些方法将文件从childbranch中排除:

方法1。如果对文件的更改是在它们自己的提交中进行的,那么您可以从这些提交中创建修补程序,并通过交互式重新基从您的分支中“删除”这些提交,但我怀疑情况是否如此。但是,如果是,请执行以下操作:

git format-patch -1 commit_in_which_you_modified_the_file
假设您的分支有2个提交,请执行以下操作:

git rebase -i HEAD~3
这将带您进入如下菜单

pick commit_hash_of_1st_commit ...
pick commit_hash_of_2st_commit ...
    pick commit_hash_of_1st_commit ...
    pick commit_hash_of_2st_commit ...
假设您不想添加的文件是第一次提交的一部分,您将通过删除该行或注释掉该行来“删除”第一次提交:

# pick commit_hash_of_1st_commit ...
pick commit_hash_of_2st_commit ...
从编辑器中退出,您应该在分支上拥有所需的内容。另外,请记住,您有一个补丁,以后可以应用它

Pros:
    - logically simple
    - idiomatically Git


Cons:
    - interactive rebase can be an overwhelming task the first time.
方法2。从分支中选择修改不希望提交的文件的特定提交。通过交互式重基,
编辑这些提交

假设您的分支有2个提交,请执行以下操作:

    git rebase -i HEAD~3
这将带您进入如下菜单

pick commit_hash_of_1st_commit ...
pick commit_hash_of_2st_commit ...
    pick commit_hash_of_1st_commit ...
    pick commit_hash_of_2st_commit ...
假设您不想添加的文件是第一次提交的一部分,您将
编辑
第一次提交:

edit commit_hash_of_1st_commit ...
pick commit_hash_of_2st_commit ...
此时,从编辑器中退出。当您这样做时,Git将应用第一次提交,但允许您在事实发生后编辑它

做:

这将取消提交和取消显示作为第一次提交一部分的更改。这为您提供了一张干净的石板,可以在一次提交的上下文中重新开始

然后:

  • git只添加您想要的更改
  • git提交
  • git添加
    其余更改:
    • git diff>mypatch.patch
优点:

  • 这是正确的方法
缺点:

  • 首先,交互式重设基础可能是一个压倒性的练习 时间
方法3。向分支添加最终提交,在该提交中,您可以撤消对文件所做的所有更改。您可以参考此最终提交的更改集,以重新构建对以后要排除的文件所做的更改

Pros:

    - easy to do (assuming there aren't too many changes)

Cons:

    - corrupts VC history
    - is not idiomatic usage of Git
方法4。如果您的分支有一次提交,
git reset HEAD~1
,然后只重新提交您想要的内容

Pros:
    - it is straightforward, basically a modification of one of the previous methods
方法5。创建一个新分支,然后重新开始。我认为不应该出现这种情况,尽管考虑到你们分支的性质,这可能并不困难,而且可能是实用的方法