How to get just one file from another branch?

GitGit BranchGit Checkout

Git Problem Overview


I am using Git and working on master branch. This branch has a file called app.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 to app.js from experiment to master 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 from experiment branch to master branch.

Git Solutions


Solution 1 - Git

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 - Git

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

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 - Git

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 - Git

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: https://stackoverflow.com/questions/888414/git-checkout-older-revision-of-a-file-under-a-new-name/888623#888623

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: https://stackoverflow.com/questions/21025314/who-is-us-and-who-is-them-according-to-git/63911630#63911630:

# 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: https://stackoverflow.com/questions/21025314/who-is-us-and-who-is-them-according-to-git/63911630#63911630.

DEALING WITH path does not have our version or path does not have their version ERRORS:

If you ever see errors like this: > bash > 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: https://stackoverflow.com/questions/43551979/git-checkout-ours-when-file-spec-includes-deleted-file/66665151#66665151.

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:

  1. Quick links to my answers I reference frequently and consider to be "git fundamentals":
    1. Various ways to create a branch in git from another branch
    2. All about checking out files or directories in git
    3. Who is "us" and who is "them" according to Git?
  2. I show some more of these examples of git checkout in my answer here: https://stackoverflow.com/questions/21025314/who-is-us-and-who-is-them-according-to-git/63911630#63911630.
  3. [my answer on "How to do a --soft or --hard git reset by path"] https://stackoverflow.com/questions/11200839/why-git-cant-do-hard-soft-resets-by-path/66539777#66539777
  4. https://stackoverflow.com/questions/888414/git-checkout-older-revision-of-a-file-under-a-new-name/888623#888623
  5. [my answer] https://stackoverflow.com/questions/43551979/git-checkout-ours-when-file-spec-includes-deleted-file/66665151#66665151
  6. [my answer] https://stackoverflow.com/questions/3107789/using-git-how-do-you-reset-the-working-tree-local-file-system-state-to-the-st/66589020#66589020

Solution 6 - Git

To restore a file from another branch, simply use the following command from your working branch:

git restore -s my-other-branch -- ./path/to/file

The -s flag is short for source i.e. the branch from where you want to pull the file.

(The chosen answer is very informative but also a bit overwhelming.)

Solution 7 - Git

Or if you want all the files from another branch:

git checkout <branch name> -- .

Solution 8 - Git

Review the file on github and pull it from there

This is a pragmatic approach which doesn't directly answer the OP, but some have found useful:

If the branch in question is on GitHub, then you can navigate to the desired branch and file using any of the many tools that GitHub offers, then click 'Raw' to view the plain text, and (optionally) copy and paste the text as desired.

I like this approach because it lets you look at the remote file in its entirety before pulling it to your local machine.

Solution 9 - Git

git checkout <branch_name> -- <paths>

More info

Solution 10 - Git

If you want the file from a particular commit (any branch), say 06f8251f

git checkout 06f8251f path_to_file

For example, on Windows:

git checkout 06f8251f C:\A\B\C\D\file.h

Solution 11 - Git

Another way is to create a patch with the differences and apply it in the master branch For instance. Let's say the last commit before you started working on app.js is 00000aaaaa and the commit containg the version you want is 00000bbbbb

The you run this on the experiment branch:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

This will create a file with all the differences between those two commits for app.js that you can apply wherever you want. You can keep that file anywhere outside the project

Then, in master you just run:

git apply ~/app_changes.git

now you are gonna see the changes in the projects as if you had made them manually.

Solution 12 - Git

There is also a simple solution for all who like to avoid unknown git commands or are afraid to wreck something:

  1. check out to the branch that the file is in
  2. copy that file to somewhere else on your computer
  3. check out to the branch the file needs to get to
  4. paste the file in place

probably takes longer than the appropriate git command... but it works and is easy to understand

Solution 13 - Git

To checkout a file from another branch is a simple one line command:

git checkout branch C:\path\to\file.cs

If you'd like multiple files

git checkout branch C:\path\to\file1.cs C:\path\to\file2.cs

Solution 14 - Git

git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

Hope this will help you. Please let me know If you have any query.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick VanderbiltView Question on Stackoverflow
Solution 1 - GitVonCView Answer on Stackoverflow
Solution 2 - GitDmitry AvtonomovView Answer on Stackoverflow
Solution 3 - GitSarathView Answer on Stackoverflow
Solution 4 - GitAlexLordThorsenView Answer on Stackoverflow
Solution 5 - GitGabriel StaplesView Answer on Stackoverflow
Solution 6 - GitConner SmithView Answer on Stackoverflow
Solution 7 - GitJesterView Answer on Stackoverflow
Solution 8 - Gitfearless_foolView Answer on Stackoverflow
Solution 9 - GitPravinView Answer on Stackoverflow
Solution 10 - GitarupjbasuView Answer on Stackoverflow
Solution 11 - GitSantiView Answer on Stackoverflow
Solution 12 - GitCHHView Answer on Stackoverflow
Solution 13 - GitKellen StuartView Answer on Stackoverflow
Solution 14 - GitRohit SainiView Answer on Stackoverflow