Switch Git branch without files checkout

54,639

Solution 1

Yes, you can do this.

git symbolic-ref HEAD refs/heads/otherbranch

If you need to commit on this branch, you'll want to reset the index too otherwise you'll end up committing something based on the last checked out branch.

git reset

Solution 2

In v2.24 git switch is something like a safe git checkout.
Hence I renamed the alias below to git hop for
"hop on the branch without changing worktree"

For the benefit of the reader:

While I think that Charles Bailey's solution is a correct one, this solution needs a tweak when switching to something, which is not a local branch. Also there should be some way how to do it with regular commands which is easy to understand. Here is what I came up with:

git checkout --detach
git reset --soft commitish
git checkout commitish

Explained:

  • git checkout --detach is the same as git checkout HEAD^{} which leaves the current branch behind and goes into "detached head state". So the next modification of HEAD no more affects any branch. Detaching HEAD does not affect the worktree nor the index.
  • git reset --soft commitish then moves HEAD to the SHA of the given commitish. If you want to update the index, too, leave --soft away, but I do not recommend to do so. This, again, does not touch the worktree, and (--soft) not the index.
  • git checkout commitish then attaches HEAD to the given commitish (branch) again. (If commitish is a SHA nothing happens.) This, too, does not affect index nor worktree.

This solution accepts everything which refers to a commit, so this is ideal for some git alias. The rev-parse below is just a test to make sure, nothing breaks in the chain, such that typos do not accidentally switch into detached head state (error recovery would be way more complex).

This leads to following git hop treeish alias:

git config --global alias.hop '!f() { git rev-parse --verify "$*" && git checkout "HEAD^{}" && git reset --soft "$*" && git checkout "$*"; }; f'

FYI, you can find it in my list of git aliases.

Solution 3

Wouldn't be a better solution to have two working directories (two working areas) with one repository, or even two repositories?

There is git-new-workdir tool in contrib/ section to help you with this.

Solution 4

I think you're looking for the plumbing command git read-tree. This will update the index but will not update any files in your working directory. For example, assuming branch is the name of the branch to read:

git read-tree branch

If you want to then commit to the branch you just read, you will also need to:

git symbolic-ref HEAD refs/heads/branch

Solution 5

You can overwrite your HEAD file with a different branch name:

echo "ref: refs/heads/MyOtherBranch" > .git/HEAD

Share:
54,639
tig
Author by

tig

Updated on July 11, 2022

Comments

  • tig
    tig almost 2 years

    Is it possible in Git to switch to another branch without checking out all files?

    After switching branch I need to delete all files, regenerate them, commit and switch back. So checking out files is just a waste of time (and there are about 14,000 files - it is a long operation).

    To make everything clear:

    I need all this to upload documentation to GitHub.

    I have a repository with the gh-pages branch. When I rebuild documentation locally, I copy it to the repository directory, commit and push to GitHub. But I was not happy, because I had two copies of documentation locally. And I decided to create an empty branch and after committing, switch to empty and delete files. But switching back is a long operation - so I asked this question.

    I know that I can just leave on the gh-pages branch and delete files, but I don't like dirty working trees.

  • Greg Hewgill
    Greg Hewgill almost 15 years
    It's probably better to use the symbolic-ref command to do this for you: git symbolic-ref HEAD refs/heads/MyOtherBranch kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html
  • Anonigan
    Anonigan almost 15 years
    You can use git-new-worktree for that instead (in contrib/)
  • tig
    tig over 14 years
    no I only need to switch branch, no any other changes - so symbolic-ref is good enough
  • tig
    tig over 14 years
    The question already got an answer: stackoverflow.com/questions/1282639/…
  • cadorn
    cadorn over 11 years
    Use echo "ebff34ffb665de0694872dceabe0edeaf50ec5a9" > .git/HEAD followed by git reset to point to a ref instead of a branch.
  • Alexander Bird
    Alexander Bird over 11 years
    Directly writing to the HEAD file is less dependable. What if you are in a subdir? For detached head (head pointing to SHA1 directly), try this: git update-ref HEAD refs/heads/otherbranch
  • Winny
    Winny almost 10 years
    If you want to check out to a fresh branch from the current branch, another way to do this is to 1. git stash 2. git checkout -b otherBranch 3. git stash pop
  • tomekwi
    tomekwi over 8 years
    @AlexanderBird: git update-ref is useful, but it also moves the tip of the current branch.
  • tomekwi
    tomekwi over 8 years
    @GregHewgill, this is the only way I know of to move the HEAD to a commit hash. Can you do that with git symbolic-ref?
  • Ryuu
    Ryuu about 7 years
    Is git-new-workdir the same as git's own worktree command? I use worktree when I want to checkout a branch into a different folder (without having to clone the entire repo).
  • Anonigan
    Anonigan about 7 years
    The git-new-worktree script predates git worktree subcommand; this command was not available when the answer was written. The script for example requires symlink support; IMHO it is better to use native support.
  • David
    David almost 7 years
    I often did something similar, which is copying my local directory before doing any "scary git stuff" as a newbie (like changing branches, etc). I'd encourage people to go that route until you feel confident in your git-fu, but to move away from it when possible. Keeping two distinct repos is ok, but adds a layer of complication and doesn't let you take advantage of git's many useful features (merging, cherry-picking, etc).
  • kyb
    kyb over 5 years
    Don't you want to use $@ rather than $*? The difference is that $@ with not expand quoted arguments, which have spaces inside.
  • Tino
    Tino over 5 years
    @kyb The function trick is stolen from another SO answer. And $@ is definitively not meant here. $* is used instead of $1, such that git switch -f b becomes the same as git switch '-f b' which should be an error. This way I can shorten the alias by leaving away some error handling like !f() { [ 1 = $# ] || { echo 'WTF!'; return 1; }; ..
  • Andry
    Andry over 4 years
    read-tree generates the error: fatal: Not a valid object name branch if there was no any git switch branch yet
  • Nils-o-mat
    Nils-o-mat over 4 years
    Very good solution. Especially, that it can be used for remote branches!
  • Joerg
    Joerg over 2 years
    I used git reset refs/heads/otherbranchdirectly to get the same result
  • tejasvi88
    tejasvi88 over 2 years
    @Andry Replace branch with your target branch name.