ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

请注意,在接受的答案中,第一个解决方案会分阶段进行更改,而第二个解决方案不会。 stackoverflow.com/a/56045704/151841
最新的答案是 git restore --source otherbranch path/to/myfile.txt(参见 the answer 中的解释)。

P
Peter Mortensen

从您希望文件结束的分支运行它:

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.txt 和 mydir

通配符不起作用,但相对路径可以

可以指定多个路径

替代:

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

是的,它会的。但这就是问题的意图。
可能很明显,但您需要使用完整的文件名......通配符不起作用!
虽然.. 这也是一个不错的方法: git show commit_id:path/to/file > path/to/file
远程:git checkout origin/otherbranch myfile.txt
使用通配符确实有效,您只需要用 '' 将它们包装起来,这样它们就不会被 shell 解释。
M
Mariusz Pawelski

我会使用 git restore(自 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 使用标准外壳重定向。如果您使用 PowerShell,那么文本编码可能会出现问题,或者如果它是 binary,您可能会得到损坏的文件。使用 git restore 更改文件全部由 git 可执行文件完成。


不错的答案。是否有 git restore 方法可以将文件从源分支复制到目标分支上的 new 文件?使用 git show 我可以使用 shell 重定向 (git show otherbranch:path/to/file1.txt > path/to/file2.txt) 来执行此操作,但由于您提到的原因,我想避免 shell 重定向。
@AdmiralAdama 不是真的。而且我认为在 git restore 中获得它的机会不大(但谁知道;))。这个重定向问题基本上是 Powershell 问题,不确定是否有任何其他 shell 有问题。我通常会回到需要使用“git show with redirection”命令的“git bash”甚至“cmd”。或者使用 GitExtensions 之类的 GUI,您可以在其中浏览提交的文件树并在任何文件上单击“另存为”。
啊,我明白了。我不使用 Powershell,所以也许 shell 重定向对我来说是 np。谢谢(你的)信息。
小改进:git restore --source=otherbranch path/to/myfile.txt 优于 git restore --source otherbranch path/to/myfile.txt 原因是在第二种情况下,tab 列出可用分支不起作用。
感谢您对“后 checkout 时代”的回复🙂
R
Rob Bednark

我最终在类似的搜索中遇到了这个问题。就我而言,我希望将另一个分支中的文件提取到与文件原始位置不同的当前工作目录中。 Answer

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

'git show' 的目的是将数据以可读格式输出到终端,不保证与文件内容完全匹配。同样,最好将一个word文档作为一个整体复制,而不是尝试将其内容复制并粘贴到另一个文档中。
我只是想查看它,以便可以将内容与当前分支进行比较(检查一些代码)。不过,我想使用 vim... 用于语法高亮等。
要在结帐前比较内容,git diff <other branch> <path to file> 效果很好。
@Gonen:从 git 版本 2.21.0 开始,“git show”手册页显示“对于普通 blob,它显示普通内容。”我不确定这是否意味着我们总是很好。我有点担心以这种方式获取图像......
P
Peter Mortensen

使用结帐命令:

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

如果文件在两个分支上都不存在,则注意合并(第二个命令)无法工作
嗯。我没有差异统计。那是差异工具的特定版本吗,因为我从未听说过它(我应该切换到它吗?):D
git diff 支持一个 --stat 参数,它基本上与 diffstat 做同样的事情。
我必须让两个分支机构都在本地签出才能使其正常工作。
P
Peter Mortensen

确保您在需要文件副本的分支中。比如:我想要master里面的sub分支文件,所以你需要checkout还是应该在master里面 git checkout master 现在把你想要的具体文件单独从sub分支里面check out到master里面, git checkout sub_branch file_path/my_file.ext 这里是sub_branch表示您拥有该文件的位置,后跟需要复制的文件名。


非常方便且解释清楚。
P
Peter Mortensen

madlep's answer 之后,您还可以使用目录 blob 从另一个分支复制一个目录。

git checkout other-branch app/**

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


请注意,首先需要正确拉出两个分支,或者使用 origin/other-branch 来引用 repo 分支。基本,但咬我。 (答案很好 - 无需编辑)
u
user151841

请注意,在接受的答案中,第一个选项 stages 来自另一个分支的整个文件(如 git add ... 已执行),第二个选项只会导致复制文件,但不会'不要暂存更改(就好像您刚刚手动编辑了文件并且有明显的差异一样)。

Git copy file from another branch without staging it

变更阶段(例如 git add filename)

$ git checkout directory/somefile.php feature-B

$ git status
On branch feature-A
Your 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 status
On branch feature-A
Your 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")

我得到“功能-B不是文件”,分支名称在前,关于这个->“目录/somefile.php”这可能会改变文件的编码吗?
S
Sławomir Lenart

抱歉,没有人提到在恢复文件之前你真的想预览与该分支相关的本地更改,所以:

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

然后,当您接受丢失(覆盖)时,您可以遵循:

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