101

Is there a Git command (or a short sequence of commands) that will safely and surely do the following?

  • Get rid of any local changes.
  • Fetch the given branch from origin if necessary
  • Checkout the given branch?

Currently I'm stuck with:

git fetch -p
git stash
git stash drop
git checkout $branch
git pull

but it's bothering me because I'm asked for password two times (by fetch and pull). Generally I would be happy with any solution as long as the password is needed only once.

A couple of notes:

  • It's a part of homebrewed deployment script for an application (the code is hosted on GitHub).
  • There should be no difference if the branch was already fetched from origin or not (i.e. the first deployment of a new branch shouldn't ideally require any additional steps).
  • The script is located on a remote machine that can be accessed by several people, hence no credentials are stored and user/password must be entered (but only once if possible).
  • I don't care about any local changes; I always want a pristine copy of the given branch (the further part of deployment script produces local changes).
  • I can't clone or export a fresh repository each time; it takes too much time.
3
  • 2
    1. git reset --hard 2. git checkout $branch 3. git pull origin $branch
    – g19fanatic
    Commented Aug 28, 2013 at 12:21
  • FYI if you use ssh keys you won't ever be prompted for a password.
    – Slam
    Commented Nov 21, 2018 at 23:28
  • @Slam not if you're using GitLab. Commented Sep 8, 2020 at 15:57

4 Answers 4

147

You could follow a solution similar to "How do I force “git pull” to overwrite local files?":

git fetch --all
git reset --hard origin/abranch
git checkout abranch 

That would involve only one fetch.

With Git 2.23+, git checkout is replaced here with git switch (presented here) (still experimental).

git switch -f $branch

(with -f being an alias for --discard-changes, as noted in Jan's answer)

Proceed even if the index or the working tree differs from HEAD.
Both the index and working tree are restored to match the switching target.


If you do not want to switch branch, but only restore a folder from another branch, then git restore is the other command which replaces the old obsolete and confusing git checkout.
I presented git restore here.

git restore --source=anotherBranch --staged] [--worktree -- aFolder
# or, shorter:
git restore -s anotherBranch -SW -- aFolder
9
  • 1
    I'm using this solution, but I added additional git checkout $branch at the end, because otherwise the current branch information returned by git was wrong.
    – szeryf
    Commented Sep 17, 2013 at 9:20
  • 1
    @VonC, Thank you. this really has overwritten master with branch.
    – psun
    Commented Jun 20, 2016 at 18:47
  • 1
    @tuxErrante So you don't want to switch branch then? In that case, git restore is for you. Nobody should use in 2021 git checkout. It is old, obsolete and confusing. git restore -s experiment -SW -- aFolder: that will restore aFolder content from the branch experiment, both working tree (W) and index (S).
    – VonC
    Commented Jun 14, 2021 at 13:52
  • 1
    @tuxErrante I have edited the answer to make the distinction (between switching branch and restoring content) clearer.
    – VonC
    Commented Jun 14, 2021 at 13:56
  • 1
    @MikeSchinkel That seems to be a typo. I have edited the answer to use the same name as the fetched branch.
    – VonC
    Commented Oct 27, 2021 at 5:23
40

Couple of points:

  • I believe git stash + git stash drop could be replaced with git reset --hard
  • ... or, even shorter, add -f to checkout command:

    git checkout -f -b $branch
    

    That will discard any local changes, just as if git reset --hard was used prior to checkout.

As for the main question: instead of pulling in the last step, you could just merge the appropriate branch from the remote into your local branch: git merge $branch origin/$branch, I believe it does not hit the remote. If that is the case, it removes the need for credensials and hence, addresses your biggest concern.

2
  • 5
    The -b may need to be capitalized. git checkout -f -B $branch resets the local branch if it already exists.
    – xer0x
    Commented Nov 10, 2017 at 18:12
  • 3
    Just git checkout -B $existing_branch_name worked for me, whereas git checkout -f -b $existing_branch_name didn't – so like @xer0x said, I think the answer is incorrect insofar as the capital -B is a requirement?
    – Suan
    Commented Apr 9, 2021 at 15:34
14

git reset and git clean can be overkill in some situations (and be a huge waste of time).

If you simply have a message like "The following untracked files would be overwritten..." and you want the remote/origin/upstream to overwrite those conflicting untracked files, then git checkout -f <branch> is the best option.

If you're like me, your other option was to clean and perform a --hard reset then recompile your project.

1
  • Not sure why this does not have more votes .... only viable option IMO
    – StackHola
    Commented May 31 at 15:46
3

The new git-switch command (starting in GIT 2.23) also has a flag --discard-changes which should help you. git pull might be necessary afterwards.

Warning: it's still considered to be experimental.

1
  • Good point. I have promoted git switch in the past (stackoverflow.com/a/57066202/6309). I have updated my 2013 answer to include that new command.
    – VonC
    Commented Jan 28, 2020 at 15:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.