261

How do I copy all files in a directory from another branch? I can list all of the files in that directory by doing

git ls-tree master:dirname

I can then copy all of the files individually by doing

git checkout master -- dirname/filename

However, using wildcards has so far been a total fail. This does nothing:

git checkout master -- dirname/*.png

Though I guess I can use a bash script to do that, there has to be an easier way, right?

Xavi
  • 20,111
  • 14
  • 72
  • 63
alexenko
  • 2,913
  • 2
  • 18
  • 10
  • Are you trying to move dirname/filename TO master or FROM master? I want to do something similar. I want to copy a file from branch1 to branch2 and I am currently in branch2. What steps should I follow? – Femn Dharamshi Mar 28 '22 at 21:31

5 Answers5

401

As you are not trying to move the files around in the tree, you should be able to just checkout the directory:

git checkout master -- dirname
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 2
    What about if I wanted to retain commit messages for the files copied over? – totels Apr 19 '11 at 11:43
  • 2
    @totels, strictly speaking there are no commit messages associated with the files; the commit message is associated with the commit object itself. This is what I'm guessing you want: `git checkout master -- dirname; git add dirname; git commit -c $COMMIT_SHA1 --reset-author;` where `$COMMIT_SHA1` could be like `branch_a` and would be the commit object which has the commit message you want. I don't know offhand how to programmatically determine the commit with most recent change to `dirname` – Alexander Bird Apr 10 '12 at 02:15
  • 1
    This has a very weird side effect. It copies `dirname` over, but it also copies any files that are in the `.gitignore` of the `master` branch. Any idea why that is? – Milimetric Feb 24 '13 at 13:08
  • 5
    Another side effect I think if the current branch has additional files not in the branch you are checking out from (in a given target folder), it will basically merge them together - maybe this is just if one is an ancestor? I'm not exactly sure of the conditions but if you have 20 files in branch A and 20 files in branch B and only 10 of them have the same file name, you end up with 30 files (at least in my case where branch A is the ancestor of branch B) – codercake Mar 20 '14 at 23:17
  • @totels check out the git command `cherry-pick`. It applies commits from other branches, but only the files that were changed in the commit(s) you want. – cs01 Apr 28 '15 at 17:39
  • 1
    @Milimetric, AFAIK the .gitignore file is not in use during a checkout. It is there to tell git about what new files it should care about. It is perfectly legal to have files in the git repo that are "ignored", although - in most cases that is not what you'd want. It sounds like you have committed files to the repo (master) and then later added that file-spec to .gitignore. This will only tell git that new files appearing matching the ignore filespec should be ignored. The original file committed to the repo is still there. Normally you'd want to remove the original file already committed too. – Spiralis Aug 09 '15 at 13:40
  • What if I want to move the files around in the tree? – emnoor May 06 '16 at 15:53
  • 4
    For people unfamiliar with git, you should be in your *target* branch when running the answer above, which (in that instance) will copy directories from the `master` branch to your target. – ffghfgh Aug 18 '16 at 14:02
  • How to undo the action above? There is no `git uncheckout master -- dirname`. – Brian Zelip Nov 06 '16 at 18:45
  • You have to have checked out the branch (in the example `master`) before this will work. – Chaim Eliyah Apr 04 '18 at 22:47
  • @totels this is exactly my need, I want to copy a bunch of files from a particular commit but keep the original authors. Have you found a solution? – SwimBikeRun Feb 23 '19 at 16:48
  • 1
    @BrianZelip You should have no uncommitted work in your current branch, for safety in these cases. I often add a local tag to my target branch when I'm performing unusual operations like this, so I can easily reset it if the changes don't turn out like I expect. – Suncat2000 Jun 15 '23 at 12:18
20

If there are no spaces in paths, and you are interested, like I was, in files of specific extension only, you can use

git checkout otherBranch -- $(git ls-tree --name-only -r otherBranch | egrep '*.java')
jalanb
  • 1,097
  • 2
  • 11
  • 37
test30
  • 3,496
  • 34
  • 26
  • 4
    It's a pity that git doesn't support this function directly. Exactly like the OP, I would have thought it would be something like `git checkout master -- *.c` – Gregory Kuhn Apr 15 '15 at 11:17
  • 1
    This answer helped me answer "How can I checkout files of a given pattern from another branch to my current working branch?" – usr-local-ΕΨΗΕΛΩΝ Apr 11 '18 at 09:37
17

To copy the directory without tracking it:

git restore --source master dirname
simleo
  • 2,775
  • 22
  • 23
  • 2
    It also removes files according to source branch while "git checkout" leaves these files untouched (at least I can observe this behavior with git 2.32) – Dmitry Feb 01 '22 at 15:07
3

In my case this simplest solution to get files from the origin branch directory was:

  • origin - remote repository alias(origin by default) sourceBranchName
  • branch with required files in directory
  • sourceBranchDirPath - relative/absolute path to the required directory with

files

git checkout origin/sourceBranchName -- sourceBranchDirPath

Example:

git checkout origin/validation_fix -- src/test/java/validation/

Result was all files from origin/validation_fix branch by src/test/java/validation/ relative path in the draft mode(uncommited)

Jackkobec
  • 5,889
  • 34
  • 34
1
git checkout sourceBranchName :

can checkout everything (root directory) from sourceBranch to your local current branch.

I tested by myself. Thx!

-- Shizheng

shizzhan
  • 41
  • 2