564

The scenario:

  1. I make some changes in a single file locally and run git add, git commit and git push
  2. The file is pushed to the remote origin master repository
  3. I have another local repository that is deployed via Capistrano with the "remote_cache" method from that remote repository
  4. Now I don't want to deploy the whole application but just update/checkout that single file.

Is this somehow possible with git? I wasn't able to find anything that would work nor was I able to figure it out. With SVN I just did svn up file and voila.

Seanny123
  • 8,776
  • 13
  • 68
  • 124
foresth
  • 5,823
  • 4
  • 17
  • 8

9 Answers9

1233

It is possible to do (in the deployed repository)

git fetch
git checkout origin/master -- path/to/file

The fetch will download all the recent changes, but it will not put it in your current checked out code (working area).

The checkout will update the working tree with the particular file from the downloaded changes (origin/master).

At least this works for me for those little small typo fixes, where it feels weird to create a branch etc just to change one word in a file.

JMM
  • 26,019
  • 3
  • 50
  • 55
qzio
  • 12,533
  • 1
  • 15
  • 8
  • 1
    Super handy, this worked great. I needed to get a composer.json file and run an update before I updated the rest of the site in production. If I had manually put the composer.json/lock files in place, when I did a pull, it would conflict saying the files already existed. By doing it this way, git recognized the files without a complaint. – David Jan 27 '14 at 05:45
  • 6
    This is the answer i was looking for. – WestCoastProjects Aug 01 '14 at 22:08
  • 33
    @Mymozaaa The double dash designates that what follows is a file name. It's to prevent git from interpreting your file name as a branch in the unfortunate case you've got two with the same name. – Joel Mellon Apr 27 '16 at 18:36
  • The problem is that you're still fetching, and if it's a large repo, that will be the expensive operation. I fear that the only alternative would be to install gitweb on the remote and then access it to retrieve the file or such. – Christian Goetze Mar 06 '17 at 23:12
  • small question, after doing that, I'm going to a different machine, then I do your actions listed above, but then in `git status` I see them as `Changes to be committed:` - meaning, I need to commit them again ? ( just noting that I wanted to refresh a single untouched file but the repo itself is touched in a different machine ) – Ricky Levi Apr 23 '17 at 07:20
  • I've done this on large repos and never had any issues. – michaeltintiuc Sep 27 '17 at 13:19
  • you can also do that with path to directory if you want. – Alon Gouldman Jul 15 '19 at 11:16
  • 1
    I am not sure why, but this solution refuses to work for me with a remote. `error: pathspec 'upstream/master' did not match any file(s) known to git` `fatal: only one reference expected, 2 given` – Alex Barker Sep 12 '19 at 21:38
  • 1
    If you want to checkout all files in a folder, just do `git checkout origin/master -- path/to/folder/*` (note the * in the end). – mcouthon Aug 26 '20 at 16:01
  • according to new naming on github, need to use branch main: `git checkout origin/main -- path/to/file` – XPS Feb 25 '21 at 14:04
  • Could someone give an example of the pathspec, I've tried foo/bar/shared/components/folder/file.js, and starting with ./, or just / , and always get "did not match any files" – smartblonde Jun 28 '21 at 23:12
  • On my patchset I was trying git checkout HEAD -- /src/main/java/com/rest/of/path/MyFile.java but git checkout origin/master -- /src/main/java/com/rest/of/path/MyFile.java was what I needed – boardtc Oct 07 '21 at 11:23
  • @qzio What does `--` mean? – John Oct 10 '22 at 07:56
  • @John [It means the command arguments ends there, after that only positional arguments can be passed.](https://unix.stackexchange.com/a/11382/128523) – Vicky Dev Oct 10 '22 at 11:57
  • @VickyDev Thank you so much. After I have carefully read the post, I fully understand what's `--` now. But I still have difficulty in understanding why there is a `--` in `git checkout origin/master -- path/to/file`. What's wrong with `git checkout origin/master path/to/file`? Could you please explain that for me? – John Oct 11 '22 at 01:55
  • 1
    RE: @AlexBarker 's issue: "pathspec" error is due to upstream not having been fetched. You need to run `git fetch upstream` instead of just `git fetch` – 7yl4r Apr 19 '23 at 17:16
83

With Git 2.23 (August 2019) and the new (still experimental) command git restore, seen in "How to reset all files from working directory but not from staging area?", that would be:

git fetch
git restore -s origin/master -- path/to/file

The idea is: git restore only deals with files, not files and branches as git checkout does.
See "Confused by git checkout": that is where git switch comes in)


codersam adds in the comments:

in my case I wanted to get the data from my upstream (from which I forked).
So just changed to:

git restore -s upstream/master -- path/to/file
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 2
    What a relief that this command finally exists... What were git-cluefull people doing before? I was restoring the whole thing and copying the individual files I needed, but it was painful. – Mike Wise Nov 13 '19 at 09:17
  • This worked for me, but in my case I wanted to get the data from my upstream (from which I forked). So just changed to `git restore -s upstream/master -- path/to/file` – coderSam May 06 '20 at 17:23
  • @coderSam Than you for this feedback. I have included your comment in the answer for more visibility. – VonC May 06 '20 at 17:30
  • 2
    `restore` is better from my testing, because it puts files in the working area instead of the staging area as `checkout` does. – Zac Jan 15 '21 at 04:58
80

Following code worked for me:

git fetch
git checkout <branch from which file needs to be fetched> <filepath> 
vsync
  • 118,978
  • 58
  • 307
  • 400
Shagun Pruthi
  • 1,813
  • 15
  • 19
21

Simply It works for me

git checkout origin/develop file_name.php
Mathivanan
  • 311
  • 2
  • 5
  • This works except that i needed to add `--`. `git checkout origin/develop -- file_name.php` – Franck May 08 '23 at 21:55
19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip
Dmitry R
  • 2,956
  • 4
  • 25
  • 45
  • 2
    This is a good solution for repos cloned over ssh, but seems this is not supported over https: `git archive --remote=https://github.com/git/git.git master:git/contrib/completion git-completion.bash | tar -x` Gives me error message: `fatal: Operation not supported by protocol.` – Alderath Mar 06 '18 at 10:18
  • 1
    was nice combined with `tar`:s `--to-stdout`, `git archive --remote="gitolite3@:" | tar xf - --to-stdout` – Puggan Se Apr 28 '18 at 23:10
10

What you can do is:

  1. Update your local git repo:

    git fetch

  2. Build a local branch and checkout on it:

    git branch pouet && git checkout pouet

  3. Apply the commit you want on this branch:

    git cherry-pick abcdefabcdef

    (abcdefabcdef is the sha1 of the commit you want to apply)

jag
  • 880
  • 5
  • 6
5
git checkout master
git pull --rebase
git checkout dev
git checkout master ./app/file.py

If you are developing in the dev branch, merge the master branch after replacing the file and push it. For example, replace app/file.py.

ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
BillowJiang
  • 51
  • 1
  • 2
  • 1
    My English is really very bad, I hope you can see.... It's all machine translated. – BillowJiang Jun 08 '22 at 09:37
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 08 '22 at 14:09
2

Or git stash (if you have changes) on the branch you're on, checkout master, pull for the latest changes, grab that file to your desktop (or the entire app). Checkout the branch you were on. Git stash apply back to the state you were at, then fix the changes manually or drag it replacing the file.

This way is not sooooo cool but it def works if you guys can't figure anything else out.

jahrichie
  • 1,215
  • 3
  • 17
  • 26
-17

I think I have found an easy hack out.

Delete the file that you have on the local repository (the file that you want updated from the latest commit in the remote server)

And then do a git pull

Because the file is deleted, there will be no conflict

  • That removes all eventual changes made to that file locally, and also pulls all the other files, which is specifically what the OP doesn't want to do. – legrojan Nov 17 '17 at 11:30
  • Instead of updating the remote branch, removing local is very bad idea. – c0der512 Dec 18 '19 at 21:32