如何将单个文件的版本从一个Git分支复制到另一个分支?

我有两个分支完全合并在一起。

然而,在合并完成后,我意识到一个文件被合并弄得一团糟(其他人做了一个自动格式化,gah),在另一个分支中更改为新版本会更容易,然后将我的一行更改重新插入到我的分支中。

那么在Git中最简单的方法是什么?

509975 次浏览

从您希望文件结束的分支运行此操作:

git checkout otherbranch myfile.txt

通用公式:

git checkout <commit_hash> <relative_path_to_file_or_dir>git checkout <remote_name>/<branch_name> <file_or_dir>

注意事项(来自评论):

  • 使用提交哈希,您可以从任何提交中提取文件
  • 这适用于文件和目录
  • 覆盖文件myfile.txtmydir
  • 通配符不起作用,但相对路径起作用
  • 可以指定多个路径

另一种选择:

git show commit_id:path/to/file > path/to/file

使用结帐命令:

  git diff --stat "$branch"git checkout --merge "$branch" "$file"git diff --stat "$branch"

我在一次类似的搜索中遇到了这个问题。在我的例子中,我希望从另一个分支中提取一个文件到当前工作目录中,该目录与文件的原始位置不同。答案

git show TREEISH:path/to/file > path/to/local/file

Madlep的回答之后,您还可以使用目录blob从另一个分支复制一个目录。

git checkout other-branch app/**

至于OP的问题,如果您只更改了其中的一个文件,这将正常工作。

  1. 确保您在需要文件副本的分支中。

    例如:我想要在master中的子分支文件,所以你需要签出或者应该在mastergit checkout master

  2. 现在从子分支中单独检查您想要的特定文件到大师

     git checkout sub_branch file_path/my_file.ext

    这里sub_branch表示您需要复制的文件后跟文件名。

请注意,在接受的答案中,第一个选项阶段从另一个分支中复制整个文件(如git add ...已执行),而第二个选项只是导致复制文件,但不会进行更改(就好像您刚刚手动编辑文件并有突出的差异一样)。

Git从另一个分支复制文件而不暂存它

阶段性变更(例如git add filename)

$ git checkout directory/somefile.php feature-B
$ git statusOn branch feature-AYour branch is up-to-date with 'origin/feature-A'.Changes to be committed:(use "git reset HEAD <file>..." to unstage)
modified:   directory/somefile.php

未完成的变动(未执行或提交):

$ git show feature-B:directory/somefile.php > directory/somefile.php
$ git statusOn branch feature-AYour branch is up-to-date with 'origin/feature-A'.Changes not staged for commit:(use "git add <file>..." to update what will be committed)(use "git checkout -- <file>..." to discard changes in working directory)
modified:   directory/somefile.php
no changes added to commit (use "git add" and/or "git commit -a")

我将使用#0(从Git 2.23开始可用):

git restore --source otherbranch path/to/myfile.txt

为什么这比其他选择更好?

  • 默认情况下git restore仅修改工作目录中的文件

git checkout otherbranch -- path/to/myfile.txt将文件复制到工作目录(磁盘上的文件),但也复制到暂存区域。它具有与手动复制文件并在其上执行git add相同的效果。默认情况下,git restore仅更改工作目录。

要获得与git checkout otherbranch -- path/to/myfile.txt相同的结果,您可以编写git restore --source otherbranch --staged --worktree path/to/myfile.txt

  • 默认情况下,当其他分支中没有文件时,git restore从工作目录中删除文件

git restore可用于使用git restore --source otherbranch path/to/dir恢复整个文件夹。您可以对git checkout执行类似的操作,但默认情况下git restore将删除otherbranch中不存在的文件。要获得git checkout行为,请使用--overlay选项。

例如,如果otherbranch上的文件比当前工作目录中的文件少(这些文件是跟踪),而没有--overlay选项git restore将删除它们。但这是一个很好的默认行为,因为您很可能希望目录的状态“与otherbranch相同”,而不是“与otherbranch相同,但有来自我当前分支的其他文件”。

要获得与git checkout otherbranch -- path/to/dir相同的结果,您可以编写git restore --source otherbranch --staged --worktree --overlay path/to/dir

  • git restore不使用shell重定向来创建文件(仅Powershell问题)

git show otherbranch:path/to/myfile.txt > path/to/myfile.txt使用标准shell重定向。如果您使用PowerShell,则可能存在文本编码问题,或者如果是二进制,可能会导致文件损坏。使用git restore更改文件全部由git可执行文件完成。

对不起,在恢复文件之前没有人提到您确实想要预览与该分支相关的本地更改,因此:

git diff <other-branch-name> -- <filename>

然后,当你接受一个丢失(覆盖),你可以遵循:

git restore --source <other-branch-name> <filename>orgit checkout <other-branch-name> <filename>