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

mad*_*lep 887 git branching-and-merging git-branch

我有两个完全合并的分支.

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

那么git中最简单的方法是什么呢?

mad*_*lep 1572

从您希望文件结束的分支运行此命令:

git checkout otherbranch myfile.txt
Run Code Online (Sandbox Code Playgroud)

通用公式:

git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>
Run Code Online (Sandbox Code Playgroud)

一些说明(来自评论):

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

替代:

git show commit_id:path/to/file > path/to/file
Run Code Online (Sandbox Code Playgroud)

  • 可能很明显,但你需要使用完整的文件名...通配符不起作用! (34认同)
  • remote:git checkout origin/otherbranch myfile.txt (13认同)
  • 是的,它会的.但这就是问题的意图. (12认同)
  • 虽然..它也是很好的方式:git show commit_id:path/to/file> path/to/file (6认同)
  • 使用通配符确实有效,您只需要将它们用'''`包裹起来,这样它们就不会被外壳程序解释。 (3认同)

Mar*_*ski 83

我会使用git restore(自 Git 2.23 起可用):

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


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

git checkout otherbranch -- path/to/myfile.txt- 它将文件复制到工作目录和暂存区(类似于手动复制此文件并git add在其上执行的效果)。git restore不接触暂存区(除非通过--staged选项告诉它)。

git show otherbranch:path/to/myfile.txt > path/to/myfile.txt使用标准外壳重定向。如果您使用 PowerShell,那么文本编码可能会出现问题,或者如果它是binary ,您可能会得到损坏的文件。随着git restore不断变化的文件是由完成的所有git可执行文件。

另一个优点是您可以使用以下命令还原整个文件夹:

git restore --source otherbranch path/to

或者git restore --overlay --source otherbranch path/to如果你想避免删除文件。例如,如果otherbranch当前工作目录中的文件少于当前工作目录中的文件(并且这些文件被跟踪),则不带--overlay选项git restore将删除它们。但这是很好的默认行为,您很可能希望目录的状态“与中相同otherbranch”,而不是“与中相同otherbranch但具有来自我当前分支的附加文件”。

  • 感谢您的“后‘结帐’时代”回复 (4认同)
  • @AdmiralAdama 不是真的。而且我认为在“git Restore”中获得它的机会不大(但谁知道呢;))。这个重定向问题基本上是Powershell问题,不确定是否有其他shell有问题。我通常会回到“git bash”甚至“cmd”,在那里我需要使用“带有重定向的`git show`”命令。或者使用像 GitExtensions 这样的 GUI,您可以浏览提交的文件树并在任何文件上单击“另存为”。 (2认同)
  • 小改进:更好的是 `git Restore --source=otherbranch path/to/myfile.txt` 相对于 `git Restore --source otherbranch path/to/myfile.txt` 原因是因为在第二种情况下,`tab`列出可用分支不起作用。 (2认同)

lkr*_*aav 79

我在类似的搜索中结束了这个问题.在我的情况下,我希望从另一个分支中提取一个文件到当前工作目录,该目录与文件的原始位置不同.答案:

git show TREEISH:path/to/file >path/to/local/file
Run Code Online (Sandbox Code Playgroud)

  • 'git show'的目的是以可读格式将数据输出到终端,这不能保证与文件内容完全匹配.同样,最好将word文档作为一个整体复制,而不是尝试将其内容复制并粘贴到另一个文档. (17认同)
  • 为了在结帐之前比较内容,`git diff &lt;other branch&gt; &lt;file的路径&gt;效果很好。 (3认同)
  • @Gonen:从git版本2.21.0开始,“ git show”手册页显示“对于普通blob,它显示普通内容”。我不确定这是否意味着我们永远都很好。我有点谨慎以这种方式获取图像... (2认同)

RzR*_*RzR 51

使用checkout命令怎么样:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
Run Code Online (Sandbox Code Playgroud)

  • 如果两个分支上都不存在该文件,则注意合并(第二个命令)不起作用 (8认同)

Moh*_*med 16

1)确保您在需要文件副本的分支机构中.例如:我想在master中使用子分支文件,因此您需要签出或者应该在master中git checkout master

2)现在单独检查你想要从子分支到master的特定文件,

git checkout sub_branch file_path/my_file.ext
Run Code Online (Sandbox Code Playgroud)

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


6ft*_*Dan 14

根据madlep的回答,您还可以使用目录blob从另一个分支复制一个目录.

git checkout other-branch app/**
Run Code Online (Sandbox Code Playgroud)

至于op的问题,如果你只改变了那里的一个文件,这将很好地工作^ _ ^


use*_*841 6

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

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

上演的变化(例如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
Run Code Online (Sandbox Code Playgroud)

未完成的更改(未上演或提交):

$ 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")
Run Code Online (Sandbox Code Playgroud)


Sła*_*art 5

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

git diff <other-branch-name> -- <filename>
Run Code Online (Sandbox Code Playgroud)

然后,当您接受丢失(覆盖)时,您可以执行以下操作:

git restore --source <other-branch-name> <filename>
or
git checkout <other-branch-name> <filename>
Run Code Online (Sandbox Code Playgroud)