git pull remote master in detached head

13.7k views Asked by At

This has been bothering me about git. I have a repository with multiple remotes, and I need to apply hotfixes to the remotes' master branches. So, I try doing:

git fetch remote1 master
git checkout remote1/master

But, I always end up in a detached head state. What is the correct way to checkout the master of a remote and apply a patch?

2

There are 2 answers

0
John Szakmeister On BEST ANSWER

None of those commands will give you a detached head. Is there something else that you're doing that you haven't written down in your question?

git fetch remote1

This will fetch anything matching the default refspec for remote1. That typically means all branches on remote1 unless you've configured it differently.

git fetch remote1 master

The above command fetches master from remote1 and stores it as FETCH_HEAD.

git pull remote1/master

This command will error out because remote1/master is not the name of a repository.

There are a few ways you could approach the problem, but it really depends on what you're trying to accomplish. The typical approach would be to create a local branch for the remote branch you want to update, and merge the corresponding branch:

git checkout -b r1-master remote1/master
git merge other/master
git push

But, it's unclear whether that's an acceptable workflow for you. Can you post more information about what you're trying to accomplish?

Update

Thanks for updating your question with the actual commands used.

git fetch remote1 master

The above command grabs the latest content of master and stores it in FETCH_HEAD. You want to leave off the master here and let Git update your remote references: git fetch remote1. At this pointer, remote1/master should be up-to-date with what's on the server.

git checkout remote1/master

This is the command that gives you a detached HEAD. Remote refs aren't treated the same as local branches (refs in refs/heads). When you checkout a remote ref, Git puts you in a detached HEAD state. I believe the idea behind this is to keep you from corrupting your view of the remote branches. The remote refs are there to serve as a snapshot of the state of the remote repository the last time you fetched. Letting you commit to them would ruin that view. Local branches are where edits need to be made.

Let's make a couple of assumptions. First, I'm going to assume that remote1 is not origin and that you have added this remote to interact with a different repository other than the primary one. Secondly, I'm assuming that you have the ability to push code to remote1.

Before going an further, let's make sure that push.default is set to a reasonable value. Run git config --global push.default. If nothing is returned, or it says matching, then let's change it. The default configuration (matching) will attempt to update all refs on a push for a particular remote. This has the side effect of removing people's work if you don't keep the local versions of your branches up-to-date. A better default is upstream, which will only push the branch that you are on. Set it with:

git config --global push.default upstream

The typical way to add a patch in Git is to create a branch, make your patch, merge it into the local representation of the remote branch, and then push the result to the remote branch.

Let's start by creating a local branch of the remote master:

git checkout -b r1-master remote1/master

Now we have a local branch called r1-master that we can update (HEAD will not be detached on this branch).

Next, do your work. This typically involves creating another branch and adding your series of patches to it:

git checkout -b fix-bugs r1-master
# Edit and commit

Next, you'll need to checkout r1-master again. While making your changes, someone could have introduced new commits on remote1/master, so let's make sure we're up-to-date:

git fetch remote1

Next, merge in the bug fix branch:

git merge fix-bugs

This will pop open an editor. Add a sensible log message about what the merge fixes, and then save and exit.

At this point, r1-master has your fix in it, but it's not on the remote server. We need to push our newly introduced fix to the remote server:

git push

At this point, r1-master and remote1/master should point to the same thing, and the remote server has been updated with your fix.

Other help

For what it's worth, it looks like you're new to Git, so let me point you at a couple of tutorials. The first is Try Git. I like it because you can try the commands right there on the web page, but it's not very in-depth. Git Immersion goes more in depth, and has an excellent presentation of the concepts behind Git. NDP Software's Git Cheatsheet is also an excellent reference on how commands affect the local and remote repository. Finally, Pro Git is a good book to get you started. The online version is free.

0
michas On

git fetch remote1 master will fetch the master branch of remote and store it in FETCH_HEAD, not in remote1/master. - You simply want git fetch remote1, or git fetch --all.

git checkout remote1/master will always put you in detached head mode, because you did not specify a local branch. - You want something like git checkout -b master remote1/master.

Please read git help fetch and git help checkout.