Git reset hard with url

Viewed 535

If I want to pull a pull request from someone without having to add their fork as a remote, I do

git pull https://github.com/<user>/<repo name>.git <branch name>

However, if there are merge conflicts, this fails, and I'd like to be able to just do

git reset --hard https://github.com/<user>/<repo name>.git/<branch name>

just as I would otherwise do e.g.

git reset --hard upstream/master

This doesn't work however, I get

fatal: invalid object name 'https'.

How can I do a hard reset to the OP's branch?

4 Answers

When you run, for example,

git pull https://github.com/<user>/<repo name>.git master

you will see this, among other output:

From https://github.com/<user>/<repo name>.git
 * branch            master     -> FETCH_HEAD

This tells you that the remote branch master was stored locally under the name FETCH_HEAD. This is not a branch name or "ref", but a so-called pseudo-ref. Nevertheless, you can use it like a branch name.

So, what you want to do is

git reset --hard FETCH_HEAD

The git pull command consists of two parts, and the first part is to run git fetch. (The second part is to run another Git command using stuff that git fetch got.) What git fetch normally does is to do two things:

  1. obtain new commits from some other Git repository; and
  2. update remote-tracking names in your own Git repository, based on the branch names obtained from the other Git repository.

To perform step 2, the other Git repository must have a name in your own Git repository. This name is called a remote and you run:

git fetch remote

which enables your Git to do steps 1 and 2.

When you run:

git fetch url

your Git is quite unable to do step 2. It can only do step 1. So that's all it does.

To set or create a branch name (of your own) to point to one of the commits obtained in step 1, you'll need to know the commit's hash ID. When fetching from a named remote, these are printed out during the git fetch operation, but with only a URL, your own Git does not save them anywhere.1 The easiest way to get them is to give the other URL a name, so that your Git saves them in step 2.


1This is not strictly true: your Git saves everything it got in the special file .git/FETCH_HEAD. You can look inside there. Note, however, that each git fetch overwrites the previous stuff, and hash IDs saved in here may not be valid by the time you look at them. Using a remote name, and git fetch remote, guarantees that you'll be able to use those hash IDs. So don't do this; use a remote name.

See also j6t's answer.

What you are currently trying to do:

git reset --hard https://github.com/<user>/<repo name>.git/<branch name>

does not make sense using the concept of an branch on an actual remote repository. The git reset operation is inherently a local operation, and, as such, you can only hard reset to the regular branches, tracking branches, or the SHA-1 hash of some commit. So, you should first git fetch to pull down all the branches, then hard reset from there.

Note that you can choose a any local ref name using the complete refspec syntax :

# create 'localname' branch, or fast forward it if 'localname' already exists :
git fetch <url> <branchname>:<localname>

# example :
git fetch <url> branchname:review/pr/1234

# create or force update by adding '+' :
git fetch <url> +branchname:review/pr/1234


# you can store the incoming ref in something other than a branch
# (e.g : a ref that doesn't start with 'refs/heads') :
#   store it outside list of branches, tags or remote branches :
git fetch <url> +branchname:refs/review/pr/1234
#   store it as if it were the remote branch of some named remote :
git fetch <url> +branchname:refs/remotes/userXYZ/pr/1234
Related