I do not think that is a correct approach. The offending callchain is: update_ref(..., "HEAD", REF_NODEREF, ...); -> lock_any_ref_for_update("HEAD", ..., REF_NODEREF); -> lock_ref_sha1_basic("HEAD", ..., REF_NODEREF, ...); . calls resolve_ref() to read HEAD to arrive at refs/heads/master . however, it notices REF_NODEREF and adjusts the ref to be updated back to "HEAD"; -> hold_lock_file_for_update(..., "HEAD", 1); -> lock_file(..., "HEAD"); . resolves symlink "HEAD" to "refs/heads/master", and locks it! This creates "refs/heads/master.lock", that is then renamed to "refs/heads/master" when unlocked. In other words, the breakage is in lock_file() and not in resolve_ref(). The latter gives the same output to the caller whether the HEAD is symbolic link or textual symref -- at least it should. The behaviour of lock_file() to resolve symlink at this point in the code comes from d58e8d3 (When locking in a symlinked repository, try to lock the original, 2007-07-25), and as explained in the log message of that commit, we cannot unconditionally remove it. Three patches to fix this issue, that come on top of the fix to t7201 (--track from detached HEAD should fail) I sent out last night, will follow. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html