Git 将旧分支合并到主分支时不应用已删除的文件。我如何告诉 Git 应用已删除的文件?

Git does not apply deleted files when merging an old branch into the master. How can I tell Git to apply deleted files?

我有一个 master 和一个 dev 分支。 我在两个方面都做出了承诺。 我还删除了 dev 中的一些文件。 我在 master 中做了其他提交,所以这个 master 分支是最近的。

我的问题是将 dev 合并到 master 不会删除文件。

Git 认为这些文件存在于 master 中,因此在合并期间保留它们。

如何合并这两个分支并强制 Git 应用在 dev 中所做的所有提交?包括已删除的文件。

感谢您的帮助!

您可以 运行 合并而不提交,确保您拥有所有正确的文件,然后 运行 提交。

  1. 执行合并

    git checkout master
    git merge --no-commit dev
    
  2. 进行必要的更改,并修复合并冲突(如果有)。

    git rm my-files-to-delete
    
  3. 提交合并,完成进程。

    git commit
    

在与分支中的更改不冲突的情况下合并绝对删除文件。

git does not preserve files during merging if they are deleted in the merging branch. - Nils_M

为了向自己证明这一点,我不得不尝试重现您的场景。观看此演示,希望您能看到您所做的不同之处。

创建新存储库

mkdir test
cd test
git init

Initialized empty Git repository in /test/.git/

创建并添加一些文件到 master 分支

echo one > 1.txt
echo two > 2.txt
git add .
git commit -m "init repo"

[master (root-commit) feaa910] init repo
2 files changed, 2 insertions(+)
create mode 100644 1.txt
create mode 100644 2.txt

创建新分支和add/delete一些文件

git checkout -b new

Switched to a new branch 'new'

echo three > 3.txt
rm 2.txt 
git add .
git status

On branch new
Changes to be committed:
(use "git reset HEAD ..." to unstage)

deleted: 2.txt
new file: 3.txt

git commit -m "changes in new"

[new db6b1a0] changes in new
2 files changed, 1 insertion(+), 1 deletion(-)
delete mode 100644 2.txt
create mode 100644 3.txt

在 master 中提交更多更改

git checkout master

Switched to branch 'master'

echo update >> 1.txt 
git commit -am "update master"

[master 912a520] update master
1 file changed, 1 insertion(+)

tree

.
├── 1.txt
└── 2.txt

确认文件在新文件中仍被删除

git checkout new

Switched to branch 'new'

tree

.
├── 1.txt
└── 3.txt

合并 new 到 master

git checkout master

Switched to branch 'master'

git merge new master

Removing 2.txt
Merge made by the 'recursive' strategy.
2.txt | 1 -
3.txt | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
delete mode 100644 2.txt
create mode 100644 3.txt

tree

.
├── 1.txt
└── 3.txt

如您所见,在 new 分支中删除的文件 2.txt 现在在合并后肯定会在 master 中删除。

我能理解这种可能情况的唯一方法是,如果您在独立的分支中创建了两个不同的文件,每个文件都具有相同的文件名。

即假设 masterdev 分支已经存在。

  1. 创建并提交 file.txtmaster
  2. 签出 dev,然后 再次 创建 并提交 file.txtdev。现在因为您创建了两个不同的文件,git 尽管文件名相同,但仍将它们视为两个独立的实体,这违背了版本控制的全部目的。
  3. 稍后从 dev
  4. 中删除 file.txt
  5. dev 合并到 master 中,低看 file.txt 仍然存在于 master 中,这是有道理的,因为就像我说的,git将这两个文件视为完全独立的。

notice 如果您 notdev 中删除 file.txt 并尝试合并,那么您会发生了合并冲突,因为 git 不知道如何处理具有相同 path/filename.

的两个不同实体

如果这是你的情况,那么我会冒着傲慢的风险说你做错了;)

版本控制系统的要点是让该工具及时管理不同阶段的文件之间的差异,以及这些更改与存储库中其他文件的关系。

我在这种情况下改进工作流程的建议是从其他分支签出特定文件:

  1. 创建并提交 file.txtmaster
  2. 签出dev,然后从其他分支

    抓取特定文件
    git checkout master -- file.txt
    

    在这种情况下,您仍将在 dev 分支上,但现在已从 master 分支添加了 file.txt

  3. 现在 git 认识到它们是同一个实体。因此您可以删除文件并在 dev

  4. 中提交删除
  5. dev 合并到 master 现在将从 master
  6. 中删除 file.txt

我遇到了同样的问题。就我而言,我认为问题在于,当我进行合并时,与远程分支相比,我的合并分支副本已经过时。 (是同事删的,不是我)

无论如何,修复它的方法是删除整个工作副本并重新克隆它。