I've got two branches that are fully merged together.
However, after the merge is done, I realise that one file has been messed up by the merge (someone else did an auto-format, gah), and it would just be easier to change to the new version in the other branch, and then reinsert my one line change after bringing it over into my branch.
So what's the easiest way in Git to do this?
git restore --source otherbranch path/to/myfile.txt
(see explanation in the answer).
Run this from the branch where you want the file to end up:
git checkout otherbranch myfile.txt
General formulas:
git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>
Some notes (from comments):
Using the commit hash, you can pull files from any commit
This works for files and directories
Overwrites the file myfile.txt and mydir
Wildcards don't work, but relative paths do
Multiple paths can be specified
An alternative:
git show commit_id:path/to/file > path/to/file
I would use git restore
(available since Git 2.23):
git restore --source otherbranch path/to/myfile.txt
Why is better than other options?
by default git restore modify files only in working directory.
git checkout otherbranch -- path/to/myfile.txt
copy file to working directory (your files on disk) but also to staging area. It's similar effect as if you would copy this file manually and executed git add
on it. git restore
by default change only working directory.
To get the same result as for git checkout otherbranch -- path/to/myfile.txt
you can write git restore --source otherbranch --staged --worktree path/to/myfile.txt
by default git restore deletes files from working directory when they are missing in other branch
git restore
can be used to restore the whole folder with git restore --source otherbranch path/to/dir
. You can do similar operation with git checkout
but git restore
by default will delete files that are missing on otherbranch
. To get git checkout
behaviour use --overlay
option.
For example, if there are fewer files on otherbranch
than in the current working directory (and these files are tracked) without --overlay
option git restore
will delete them. But this is good default behaviour, you most likely want the state of directory to be "the same like in otherbranch
", not "the same like in otherbranch
but with additional files from my current branch".
To get the same result as for git checkout otherbranch -- path/to/dir
you can write git restore --source otherbranch --staged --worktree --overlay path/to/dir
git restore doesn't use shell redirection to create file (Powershell only problem)
git show otherbranch:path/to/myfile.txt > path/to/myfile.txt
uses standard shell redirection. If you use PowerShell then there might be problem with text encoding or you could get broken file if it's binary. With git restore
changing files is done all by the git
executable.
git restore
way to copy a file from the source branch to a new file on the target branch? With git show I can do this with shell redirection (git show otherbranch:path/to/file1.txt > path/to/file2.txt
), but I want to avoid shell redirection for the reasons you mentioned.
git restore
(but who know ;)). This redirection issues are basically Powershell problem, not sure if there is any other shell that have problem with it. I usually go back to "git bash" or even "cmd" where I need to use "git show
with redirection" commands. Or use GUI like GitExtensions where you can browse file tree of commit and click "Save as" on any file.
git restore --source=otherbranch path/to/myfile.txt
against git restore --source otherbranch path/to/myfile.txt
the reason is because in the second case, tab
to list the available branches doesn't work.
checkout
-era" response 🙂
I ended up at this question on a similar search. In my case I was looking to extract a file from another branch into current working directory that was different from the file's original location. Answer:
git show TREEISH:path/to/file > path/to/local/file
git diff <other branch> <path to file>
works well.
Use the checkout command:
git diff --stat "$branch"
git checkout --merge "$branch" "$file"
git diff --stat "$branch"
git diff
supports an --stat
argument which basically does the same thing as diffstat.
Ensure you're in branch where you need a copy of the file. For example: I want sub branch file in master, so you need to checkout or should be in master git checkout master Now check out the specific file alone you want from the sub branch into master, git checkout sub_branch file_path/my_file.ext Here sub_branch means where you have that file followed by filename you need to copy.
Following madlep's answer, you can also just copy one directory from another branch with the directory blob.
git checkout other-branch app/**
As to the OP's question if you've only changed one file in there, this will work fine.
origin/other-branch
for referring to the repo branch. Basics, but bit me. (the answer is great - no editing required)
Please note that in the accepted answer, the first option stages the entire file from the other branch (like git add ...
had been performed), and that the second option just results in copying the file, but doesn't stage the changes (as if you had just edited the file manually and had outstanding differences).
Git copy file from another branch without staging it
Changes staged (e.g. 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
Changes outstanding (not staged or committed):
$ 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")
Sorry, no one mentioned that before restoring a file you really want to preview local changes in relation to that branch, so:
git diff <other-branch-name> -- <filename>
Then when you're accepting a lost (overwritting), you can follow by:
git restore --source <other-branch-name> <filename>
or
git checkout <other-branch-name> <filename>
Success story sharing
''
so they don't get interpreted by the shell.