Git: restore files or folders from another branch

You can copy a single file or an entire folder from another Git branch without switching to that branch or merging it. Modern versions of Git provide git restore for this purpose.

Suppose you want to copy a file from feature-branch into main. First, switch to the branch that should receive the file:

git switch main

Then restore the file from the source branch:

git restore --source feature-branch -- src/js/some-file.js

The -- separates the branch name from the path. It prevents ambiguity if a branch and a file have the same name. The command overwrites uncommitted changes to the selected path, so commit or stash anything you want to keep first.

By default, git restore updates only the working tree, so you can review the change before staging it:

git status --short
git diff -- src/js/some-file.js
git add src/js/some-file.js
git diff --staged -- src/js/some-file.js
git commit -m "Restore file from feature branch"

If the file is new to main, it appears as untracked in git status and does not appear in git diff until you stage it. The staged diff therefore provides the final review in both cases.

To restore an entire folder, pass the folder path instead:

git restore --source feature-branch -- src/js/
git diff -- src/js/
git add src/js/
git commit -m "Restore JavaScript files from feature branch"

Restoring a folder makes its tracked contents match the source branch. That can also remove tracked files that exist on main but not on feature-branch, so review the diff carefully.

You can also use a commit hash or tag in place of feature-branch. This copies the selected paths as they existed at that revision; it does not merge the branch or preserve the copied changes as a separate piece of history.

Using git checkout on older Git versions

Git versions older than 2.23 do not have git restore. The older equivalent is:

git checkout main
git checkout feature-branch -- src/js/some-file.js

Unlike the git restore example above, this form updates both the working tree and the index, so the file is staged immediately. Review the staged change with git diff --staged before committing it.