CodeManX
CodeManX

Reputation: 11885

Checkout remote branch in a failsafe way, throwing local changes away?

Common recommendations to reset your working copy (master branch) to the state of the upstream branch seem to be:

git checkout master
git fetch
git reset --hard origin/master

and

git checkout master
git reset --hard
git pull

Or with detaching the HEAD:

git checkout origin/master
git reset --hard
git pull origin master

The problem I have with these is that they are not fail-safe. The working copy could be in a state which results in a checkout error:

error: Your local changes to the following files would be overwritten by checkout:

...

Please commit your changes or stash them before you switch branches. Aborting

What seems to do the trick is the following:

git fetch
git checkout --force origin/master -B master

The checkout is forced, getting rid of local changes. The remote branch is checked out, overwriting a possibly existing local branch master and not detaching the HEAD. origin/master should refer to the latest remote HEAD because git fetch is run before the checkout.

My question: are there additional Git corner cases which could prevent these commands from failing? Some weird working copy state, like in the middle of a merge, with untracked files becoming tracked or vice versa, ignored files being staged, submodule related things or something along these lines?

What commands would be equivalent to deleting the entire working copy and cloning the repository again? (I don't want to actually re-clone because the repository in question is huge.)

Upvotes: 0

Views: 931

Answers (1)

Jay
Jay

Reputation: 3950

A force-checkout will overwrite untracked files in the working directory if they are tracked in the to-be checked-out branch, but it will not remove untracked files that are not part of the checkout.

Clean checkout the way I recommend it:

First clean up the working directory:

E.g. use one of these approaches:

  • stash changes and untracked files away for possible later use with
    git stash save -u 'some message'.
    If you ever need them again, you can restore those changes with
    git stash apply stash{0}
    If you want to inspect the stashed changes you can do so with
    git stash show -p stash@{0}
    and if you want to inspect the stashed untracked files with
    git show stash@{0}^3.

    Note: The stash number (0) may change if you save more stashes after this.
    Consult git stash list if in doubt which number to use.
  • stash changes and untracked files and ignored files by first double-checking which ones there are using git status --ignored and then using git stash save --all 'some message'.
  • delete changes and untracked changed for good with git reset --hard HEAD; git clean -f -d. Make sure you that you actually want to do this as you cannot undo this.
  • delete changes untracked files and ignored files by first double-checking which ones there are using git status --ignored and then using git clean -f -d -x. Make sure you that you actually want to do this as you cannot undo this. Usually this should not be necessary to avoid checkout collisions.

After your cleanup of your working directory you should be able to checkout whichever branch you want without collisions.


(I don't want to actually re-clone because the repository in question is huge.)

Not sure if you're aware, so just in case that the bandwith is the problem here:

You can clone repositories locally. So instead of re-cloning e.g. from github, you could instead do a local git clone ./repo repo_new and the adjust the origin in the new repo e.g. with git remote set-url https://mygitsvr/user/repo.

Upvotes: 1

Related Questions