How to get just one file from another branch?
Solution 1
git checkout master # first get back to master
git checkout experiment -- app.js # then copy the version of app.js
# from branch "experiment"
See also git how to undo changes of one file?
Update August 2019, Git 2.23
With the new git switch
and git restore
commands, that would be:
git switch master
git restore --source experiment -- app.js
By default, only the working tree is restored.
If you want to update the index as well (meaning restore the file content, and add it to the index in one command):
git restore --source experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -SW -- app.js
As Jakub Narębski mentions in the comments:
git show experiment:path/to/app.js > path/to/app.js
works too, except that, as detailed in the SO question "How to retrieve a single file from specific revision in Git?", you need to use the full path from the root directory of the repo.
Hence the path/to/app.js used by Jakub in his example.
As Frosty mentions in the comment:
you will only get the most recent state of app.js
But, for git checkout
or git show
, you can actually reference any revision you want, as illustrated in the SO question "git checkout revision of a file in git gui":
$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME
would be the same is $FILENAME is a full path of a versioned file.
$REVISION
can be as shown in git rev-parse
:
experiment@{yesterday}:app.js # app.js as it was yesterday
experiment^:app.js # app.js on the first commit parent
experiment@{2}:app.js # app.js two commits ago
and so on.
schmijos adds in the comments:
you also can do this from a stash:
git checkout stash -- app.js
This is very useful if you're working on two branches and don't want to commit.
Solution 2
Everything is much simpler, use git checkout for that.
Suppose you're on master
branch, to get app.js from new-feature
branch do:
git checkout new-feature path/to/app.js
// note that there is no leading slash in the path!
This will bring you the contents of the desired file. You can, as always, use part of sha1 instead of new-feature branch name to get the file as it was in that particular commit.
Note:new-feature
needs to be a local branch, not a remote one.
Solution 3
git checkout branch_name file_name
Example:
git checkout master App.java
This will not work if your branch name has a period in it.
git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.
Solution 4
Supplemental to VonC's and chhh's answers:
git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative, then just use:
git show experiment:app.js > app.js
or
git checkout experiment -- app.js
Solution 5
All about checking out files or directories in git
1. How to check out one or more files or directories from another branch or commit hash into your currently-checked-out branch:
# check out all files in <paths> from branch <branch_name>
git checkout <branch_name> -- <paths>
Source: http://nicolasgallagher.com/git-checkout-specific-files-from-another-branch/.
See also man git checkout
.
Examples:
# Check out "somefile.c" from branch `my_branch`
git checkout my_branch -- somefile.c
# Check out these 4 files from `my_branch`
git checkout my_branch -- file1.h file1.cpp mydir/file2.h mydir/file2.cpp
# Check out ALL files from my_branch which are in
# directory "path/to/dir"
git checkout my_branch -- path/to/dir
If you don't specify, the branch_name
it is automatically assumed to be HEAD
, which is your most-recent commit of the currently-checked-out branch. So, you can also just do this to check out "somefile.c" and have it overwrite any local, uncommitted changes:
# Check out "somefile.c" from `HEAD`, to overwrite any local, uncommitted
# changes
git checkout -- somefile.c
# Or check out a whole folder from `HEAD`:
git checkout -- some_directory
2. Going Further: How to check out any file from any branch or commit hash into any location on your computer (VERY USEFUL!):
# General form
git show my_branch_or_commit_hash:my_file.cpp > any/path/my_file.cpp
# Example: check out `main.cpp` from 3 commits ago in your currently-checked-out
# branch (3 commits prior to `HEAD`, or `HEAD~3`) into a temporary directory
mkdir ../temp
git show HEAD~3:main.cpp > ../temp/main_old.cpp
Source where I learned this: @Jakub Narębski's answer to: git-checkout older revision of a file under a new name
3. What if you're in the middle of resolving git merge
, git cherry-pick
, git rebase
, or git revert
changes?
Well, in that case, you better do the following. Note: to know which commit hash or branch --theirs
and --ours
are in each context, see my answer here: Who is "us" and who is "them" according to Git?:
# Keep `--theirs` for all conflicts within this file
git checkout --theirs -- path/to/some/file
# OR: keep `--ours` for all conflicts within this file
git checkout --ours -- path/to/some/file
OR:
# Keep `--theirs` for all conflicts within files inside this dir
git checkout --theirs -- path/to/some/dir
# OR: keep `--ours` for all conflicts within files inside this dir
git checkout --ours -- path/to/some/dir
Do NOT do the regular checkout
form in the previous section before this, unless that's what you really want to do. See the "WARNING WARNING WARNING" section in my answer referenced above: Who is "us" and who is "them" according to Git?.
DEALING WITH path does not have our version
or path does not have their version
ERRORS:
If you ever see errors like this:
error: path 'path/to/some/dir/file1.cpp' does not have our version # OR error: path 'path/to/some/dir/file1.cpp' does not have their version
...when running the commands above, then you simply need to git rm
those files first and then try the git checkout --ours
or git checkout --theirs
command again. See my answer here for a detailed explanation of these commands, including a form to automatically find and delete those errored files for you: git checkout --ours when file spec includes deleted file.
4. What if you want to reset a certain file or directory to exactly match that file or directory's state in another commit or branch?
In this case, git checkout my_branch -- some_file_or_dir
is NOT enough, because if you have files in the specified directory which exist in your currently-checked-out branch or commit but do NOT exist in my_branch
, then you'd like them to be deleted locally, but git checkout
does NOT delete any files which exist locally but not on the specified commit, rather, it only overwrites files locally with their versions from the specified commit. So, to also delete files locally which should not be there, so that what you end up with locally is an exact copy of what you have on commit or branch my_branch
, you must do the following:
# How to "hard reset" "path/to/some/file_or_dir" to its state exactly as it was
# at commit or branch `my_branch`
#
# WARNING: `git status` should be TOTALLY CLEAN before beginning this process!
# Otherwise, you risk PERMANENTLY LOSING any uncommitted changes shown by
# `git status`, since `git clean -fd` 'f'orce deletes ALL files
# and 'd'irectories which are in your current working tree (file system), but
# which are *not* in the path you specify below in commit or branch `my_branch`.
# Therefore, anything NOT already committed gets **permanently lost** as though
# you had used `rm` on it!
git reset my_branch -- path/to/some/file_or_dir
git checkout-index -fa
git clean -fd # SEE WARNING ABOVE!
git commit -m "hard reset path/to/some/file_or_dir to its state \
as it was at my_branch"
See my own answer here for more details on this: Why git can't do hard/soft resets by path?
See also:
- Quick links to my answers I reference frequently and consider to be "git fundamentals":
- I show some more of these examples of
git checkout
in my answer here: Who is "us" and who is "them" according to Git?. - [my answer on "How to do a --soft or --hard git reset by path"] Why git can't do hard/soft resets by path?
- git-checkout older revision of a file under a new name
- [my answer] git checkout --ours when file spec includes deleted file
- [my answer] Using git, how do you reset the working tree (local file system state) to the state of the index ("staged" files)?
Nick Vanderbilt
Updated on July 11, 2022Comments
-
Nick Vanderbilt almost 2 years
I am using Git and working on
master
branch. This branch has a file calledapp.js
.I have an
experiment
branch in which I made a bunch of changes and tons of commits. Now I want to bring all the changes done only toapp.js
fromexperiment
tomaster
branch.How do I do that?
Once again I do not want a merge. I just want to bring all the changes in
app.js
fromexperiment
branch tomaster
branch.-
givanse over 10 yearsthis is a duplicate of How do I copy a version of a single file from one git branch to another?
-
Alexei Martianov about 5 yearsExcepted answer and others as of today answer how to copy file's contents, that's what I wanted myself when I found that one. However, if read exactly, Nick wanted to bring changes, not full text, and file in
master
may diverge fromexperiment
, e.g. can contain changes merged from other branches which would be lost in file is just copied. P.S. on the other hand he does not want to merge, but as far as I knowgit merge
term is for branch only, not for specific file, so no contradiction here.
-
-
Frosty over 14 yearsOne note: you will only get the most recent state of app.js, you will not get any history carried over from the experiment branch.
-
talyric about 10 yearsI find it helpful to always specify the origin
git checkout origin/source_branch path/to/file
because if you have neglected to update the source branch of your local repo, you might get an old version of the file...Ask me how I know. ;) -
ThomasReggi about 10 yearsSo I can't import a file from master to another branch, only from other branches to master. Thoughts?
-
VonC about 10 years@ThomasReggi you should be able to import (checkout) a file from any branch to any current branch. If you can't, that can be a good question to ask here, with specific details like the exact error message, and version of Git and OS used.
-
ThomasReggi about 10 yearsI got it to work, I wanted to import a file that I didn't pull down from github. Sorry @VonC! So it was just importing the same file.
-
Evan Lenz almost 9 yearsIn a sub-directory, you can also use
experiment:./app.js
. (You don't have to specify the full path.) I learned this thanks to the very helpful error message git gave me: "Did you mean 'mybranch:full/path/to/my/file.xsl' aka 'mybranch:./file.xsl'?" Yes, I did! I don't think I've ever been so delighted by a fatal error message. -
VonC almost 9 years@EvanLenz sounds great! What version of Git are you using?
-
VonC over 8 years@vehsakul the syntax is for a checkout of a file on any branch:
git checkout $REVISION -- $FILENAME
.experiment@{yesterday}
means the version as of yesterday on the branchexperiment
, even if you are onmaster
branch. -
Mymozaaa over 8 yearsShould'nt we do
git checkout origin source_branch path/to/file
to get the branch on the remote? So it is VERY the last version of the file? See this link for difference between these two commands : stackoverflow.com/questions/26125162/… -
ThomasG over 8 years@Mymozaaa the question did not mention remotes, thus the assumption that it is a purely local repo
-
user1366265 about 8 yearsWill this command bring the file's history, or just the last version of the file?
-
ThomasG about 8 years@user1366265 this command will put the file as it was in the particular commit you specify or the head of the branch you specify. There is no such a thing as "history of a file", all history information is only stored in branches.
-
Tomasz Gandor almost 8 yearsI see that the checkout file is immediately added to index after this operation (as in "Changes to be commited").
-
Tomasz Gandor almost 8 years@talyric - but if you haven't pulled or fetched, you'll be toast anyway. After fetch it's good to do a
git push . origin/otherbranch:otherbranch
anyway (update local branch without checking it out, but use only for fast-forward). -
Tomasz Gandor almost 8 yearsCool! I hate specifying long paths. Is the double dash (
--
) between the branch name and paths optional? Is it only to prevent paths, which would start with a dash, from being treated as options / switches? -
VonC almost 8 years@TomaszGandor Yes, I mention that in stackoverflow.com/a/21066489/6309, where git show would not modify the index, but git checkout does modify the index.
-
AlexLordThorsen almost 8 yearsHonestly I don't know. I didn't even notice that I had forgotten the double dash until you pointed this out.
-
wviana over 7 yearsWhy do you use
--
, I've done the same without it. Am I missing something ? -
VonC over 7 years@wviana It is to separate options from arguments: stackoverflow.com/a/1192194/6309
-
Lidia over 7 yearsWhile on master I tried
git checkout some_branch -- my.file
but it gave mefatal: invalid reference: some_branch
. Had to first dogit checkout some_branch
, thengit checkout master
, thengit checkout some_branch -- my.file
to only get that file from branch. -
VonC over 7 years@lid probably because you only had origin/some_branch.
-
Lidia over 7 years@VonC Yes, origin/some_branch works. It also gets me the latest version of the file on the branch, which is what I wanted. Thanks!
-
greatvovan almost 7 yearsThe initial queston contains "just one file".
-
bluenote10 over 6 yearsThis seems to automatically stage the checked-out file. Is it possible to do the same without staging?
-
Alois Mahdal over 6 years@TomaszGandor The
--
is optional, but it's more useful to avoid conflict with branch names. For example,git checkout -- foo
means "check out file foo from HEAD" (ie. overwrite local changes in foo, ie. a subset ofgit reset --hard
), butgit checkout foo
could mean that or "let's go to branch foo". -
Amare almost 6 yearsthis replaces existing files rather than merging
-
Xeverous almost 6 yearsThis
.
makes a huge difference: instead of moving to another branch it copies all files from there while still leaving you on the current one. You get contents from other branch without going into it. -
schmijos over 5 yearsI'd like to mention here, that you also can do this from a stash:
git checkout stash -- app.js
. This is very useful if you're working on two branches and don't want to commit. -
VonC over 5 years@schmijos Thank you. I have included your comment in the answer for more visibility.
-
Terry Tan over 5 yearsIs that just copying a file? What happens if we merge?
-
VonC over 5 years@TerryTan "What happens if we merge?": nothing more (or less) than if you manually copied over the content of that file in your branch: if there is no further modification (for that file) in both branches, a merge will ignore said file.
-
VonC about 5 years@PhilipRego I would like to see that case illustrated in a new separate question: that way, I will know what to fix.
-
Philip Rego about 5 yearscouldnt reproduce
-
Philip Rego about 5 yearsI found it. It should be covered in this answer. See that I get "invalid reference", but im able to fetch the branch. $ git checkout issue/2020.07.04 -- pom.xml fatal: invalid reference: issue/2020.07.04 $ git fetch origin issue/2020.07.04 From example.com * branch issue/2020.07.04 -> FETCH_HEAD
-
VonC about 5 years@PhilipRego Interesting. For testing, I still think a separate question illustrating the bug in more details (with OS and Git version) would be useful. Once we all understand what is going wrong, I will edit this answer.
-
Philip Rego about 5 yearsStack doens't let me post questions anymore. git version 2.17.1.windows.2 Windows 7
-
VonC about 5 years@PhilipRego As I mentioned before, this would be better addressed as a new question. You might consider creating a new account just for that purpose (and request merging that new account later on)
-
Philip Rego about 5 yearsHowever copy and pasting the raw file is likely to cause unwanted character changes in your git diff. It's safer to save the file directly to your project to ensure no changes.
-
Bret about 5 years@PhilipRego This answer is correct. I'm guessing there is different capitalization or punctuation in your branch, or you only have a remote branch and not a local one. See the git checkout doc: git-scm.com/docs/git-checkout#Documentation/…
-
Philip Rego about 5 years@Bret I found it doesn't work when the branch name has a period. I suggested an edit
-
Turtle almost 5 yearsThanks for taking the time to answer! But this does not answer the question, and a good answer that is very detailled has already been posted 9 years ago. There is no need to bump the question.
-
arupjbasu almost 5 yearsThis is a valid practical scenario . The answer deals correctly with the branch , but what about looking at a particular commit of the branch .
-
Fried Brice over 4 yearsSee Dmitry Avtonomov's Answer.
-
VonC over 4 years@FriedBrice See my answer: these days, it would be
git restore -s new-feature path/to/app.js
-
majurageerthan about 4 years
git fetch
before checkout -
Thomio over 3 yearsThis solution also works when the file doesn't exist in the current branch
-
kkm over 3 yearsWhy -1: first. this is an answer, but not to the question asked. Second, this overwriting all files in the current directory and all subdirectories unconditionally. Perhaps you shouldn't assume that the OP is a Git pro. Many people, in my experience, treat Git command like magic spells, and this form of the command is really dangerous. IMO, if you also allow me an advice not asked for, you'll make the community a better service by removing your answer.
-
Pooja Sonkar about 3 yearsWhat if I have to change the folder in which I want my code to be copied?
-
VonC about 3 years@PoojaSonkar I suppose you would need to restore first, then rename the folder. If I have misinterpreted your comment, please make it a new question, with a clear example.
-
jtlz2 about 2 yearsWARNING!! Never ever do
git clean -fd
without first understanding what it will do. Mercifully Jetbrains kept backups of these files for me. Think,\rm -rf *
... -
Gabriel Staples about 2 years@jtlz2, I added a long WARNING block in a comment above that code. Does that cover it?