IT

내 GIT 하위 모듈 HEAD가 마스터에서 분리 된 이유는 무엇입니까?

lottoking 2020. 7. 5. 07:46
반응형

내 GIT 하위 모듈 HEAD가 마스터에서 분리 된 이유는 무엇입니까?


GIT 하위 모듈을 사용하고 있습니다. 서버에서 변경 사항을 가져온 후 여러 번 내 하위 모듈 헤드가 마스터 분기에서 분리됩니다.

왜 그런가요?

나는 항상해야합니다 :

git branch
git checkout master

하위 모듈이 항상 마스터 분기를 가리 키도록하려면 어떻게해야합니까?


편집하다:

유효한 솔루션 @Simba Answer참조하십시오.

submodule.<name>.update변경하려는 게다가, 참조되는 문서를 - 기본checkout
submodule.<name>.branch 원격 지사를 지정 추적합니다 - 기본master


오래된 답변 :

개인적으로 나는 시간이 지남에 따라 작동을 멈출 수있는 외부 링크로 직접 연결되는 답변을 싫어하고 (질문이 중복되지 않는 한) 여기에서 내 답변을 확인 하십시오 . 응답하지 않으면 설명서를 읽으십시오. "

다시 질문으로 돌아가십시오. 왜 그런 일이 발생합니까?

당신이 묘사 한 상황

서버에서 변경 사항을 가져온 후 여러 번 내 하위 모듈 헤드가 마스터 분기에서 분리됩니다.

이것은 하나가 사용하지 않는 일반적인 경우입니다 서브 모듈을 너무 자주하거나 함께 시작 서브 모듈 . 서브 모듈 의 HEAD가 분리 되는 시점에 우리 모두 가 있었다고 말한 것이 정확하다고 생각합니다 .

  • 원인 : 서브 모듈이 올바른 분기를 추적하지 않습니다 (기본 마스터).
    해결 방법 : 하위 모듈이 올바른 분기를 추적하고 있는지 확인하십시오
$ cd <submodule-path>
# if the master branch already exists locally:
# (From git docs - branch)
# -u <upstream>
# --set-upstream-to=<upstream>
#    Set up <branchname>'s tracking information so <upstream>
#    is considered <branchname>'s upstream branch.
#    If no <branchname> is specified, then it defaults to the current branch.
$ git branch -u <origin>/<branch> <branch>
# else:
$ git checkout -b <branch> --track <origin>/<branch>
  • 원인 : 부모 저장소가 하위 모듈 분기를 추적하도록 구성되어 있지 않습니다.
    원 원인 인 및 해해 결결 방 방법 법 : 다음 두 명령으로 새 하위 모듈을 추가하여 하위 모듈이 원격 분기를 추적하도록하십시오.
    • 먼저 git에게 리모컨을 추적하도록 지시하십시오 <branch>.
    • 체크 아웃 대신 리베이스 또는 병합을 수행하도록 git에 지시합니다.
    • git에게 원격에서 서브 모듈을 업데이트하도록 지시합니다.
    $ git submodule add -b <branch> <repository> [<submodule-path>]
    $ git config -f .gitmodules submodule.<submodule-path>.update rebase
    $ git submodule update --remote
  • 이와 같은 기존 서브 모듈을 추가하지 않은 경우 쉽게 수정할 수 있습니다.
    • 먼저 서브 모듈에 추적하려는 분기가 체크 아웃되어 있는지 확인하십시오.
    $ cd <submodule-path>
    $ git checkout <branch>
    $ cd <parent-repo-path>
    # <submodule-path> is here path releative to parent repo root
    # without starting path separator
    $ git config -f .gitmodules submodule.<submodule-path>.branch <branch>
    $ git config -f .gitmodules submodule.<submodule-path>.update <rebase|merge>

일반적인 경우, 위의 구성 문제 중 하나와 관련되어 있으므로 DETACHED HEAD가 이미 수정되었습니다.

DETACHED HEAD를 고칠 때 .update = checkout

$ cd <submodule-path> # and make modification to your submodule
$ git add .
$ git commit -m"Your modification" # Let's say you forgot to push it to remote.
$ cd <parent-repo-path>
$ git status # you will get
Your branch is up-to-date with '<origin>/<branch>'.
Changes not staged for commit:
    modified:   path/to/submodule (new commits)
# As normally you would commit new commit hash to your parent repo
$ git add -A
$ git commit -m"Updated submodule"
$ git push <origin> <branch>.
$ git status
Your branch is up-to-date with '<origin>/<branch>'.
nothing to commit, working directory clean
# If you now update your submodule
$ git submodule update --remote
Submodule path 'path/to/submodule': checked out 'commit-hash'
$ git status # will show again that (submodule has new commits)
$ cd <submodule-path>
$ git status
HEAD detached at <hash>
# as you see you are DETACHED and you are lucky if you found out now
# since at this point you just asked git to update your submodule
# from remote master which is 1 commit behind your local branch
# since you did not push you submodule chage commit to remote. 
# Here you can fix it simply by. (in submodules path)
$ git checkout <branch>
$ git push <origin>/<branch>
# which will fix the states for both submodule and parent since 
# you told already parent repo which is the submodules commit hash 
# to track so you don't see it anymore as untracked.

그러나 하위 모듈에 대해 이미 로컬로 변경하고 커밋 한 경우 'git checkout'을 실행할 때 원격으로 푸시하면 Git이 알려줍니다.

$ git checkout <branch>
Warning: you are leaving 1 commit behind, not connected to any of your branches:
If you want to keep it by creating a new branch, this may be a good time to do so with:

임시 지점을 만드는 권장 옵션이 좋을 수 있습니다. 그런 다음 이러한 지점 등을 병합하면됩니다. 그러나 개인적 git cherry-pick <hash>으로이 경우 에만 사용 합니다.

$ git cherry-pick <hash> # hash which git showed you related to DETACHED HEAD
# if you get 'error: could not apply...' run mergetool and fix conflicts
$ git mergetool
$ git status # since your modifications are staged just remove untracked junk files
$ rm -rf <untracked junk file(s)>
$ git commit # without arguments
# which should open for you commit message from DETACHED HEAD
# just save it or modify the message.
$ git push <origin> <branch>
$ cd <parent-repo-path>
$ git add -A # or just the unstaged submodule
$ git commit -m"Updated <submodule>"
$ git push <origin> <branch>

하위 모듈을 DETACHED HEAD 상태로 전환 할 수있는 경우가 더 있지만 특정 사례를 디버깅하는 방법을 조금 더 이해하기를 바랍니다.


나는 항상 분리하는 것에 지쳤으므로 모든 모듈에 대해 셸 스크립트를 사용합니다. 나는 모든 서브 모듈이 마스터에 있다고 가정합니다 : 여기 스크립트가 있습니다 :

#!/bin/bash
echo "Good Day Friend, building all submodules while checking out from MASTER branch."

git submodule update 
git submodule foreach git checkout master 
git submodule foreach git pull origin master 

부모 모듈에서 실행하십시오.


Adding a branch option in .gitmodule is NOT related to the detached behavior of submodules at all. The old answer from @mkungla is incorrect, or obsolete.

From git submodule --help, HEAD detached is the default behavior of git submodule update --remote.

First, there's no need to specify a branch to be tracked. origin/master is the default branch to be tracked.

--remote

Instead of using the superproject's recorded SHA-1 to update the submodule, use the status of the submodule's remote-tracking branch. The remote used is branch's remote (branch.<name>.remote), defaulting to origin. The remote branch used defaults to master.

Why

So why is HEAD detached after update? This is caused by the default module update behavior: checkout.

--checkout

Checkout the commit recorded in the superproject on a detached HEAD in the submodule. This is the default behavior, the main use of this option is to override submodule.$name.update when set to a value other than checkout.

To explain this weird update behavior, we need to understand how do submodules work?

Quote from Starting with Submodules in book Pro Git

Although sbmodule DbConnector is a subdirectory in your working directory, Git sees it as a submodule and doesn’t track its contents when you’re not in that directory. Instead, Git sees it as a particular commit from that repository.

The main repo tracks the submodule with its state at a specific point, the commit id. So when you update modules, you're updating the commit id to a new one.

How

If you want the submodule merged with remote branch automatically, use --merge or --rebase.

--merge

This option is only valid for the update command. Merge the commit recorded in the superproject into the current branch of the submodule. If this option is given, the submodule's HEAD will not be detached.

--rebase

Rebase the current branch onto the commit recorded in the superproject. If this option is given, the submodule's HEAD will not be detached.

All you need to do is,

git submodule update --remote --merge
# or
git submodule update --remote --rebase

Recommended alias:

git config alias.supdate 'submodule update --remote --merge'

# do submodule update with
git supdate

There's also an option to make --merge or --rebase as the default behavior of git submodule update, by setting submodule.$name.update to merge or rebase.

Here's an example about how to config the default update behavior of submodule update in .gitmodule.

[submodule "bash/plugins/dircolors-solarized"]
    path = bash/plugins/dircolors-solarized
    url = https://github.com/seebi/dircolors-solarized.git
    update = merge # <-- this is what you need to add

Or configure it in command line,

# replace $name with a real submodule name
git config -f .gitmodules submodule.$name.update merge

References


Check out my answer here: Git submodules: Specify a branch/tag

If you want, you can add the "branch = master" line into your .gitmodules file manually. Read the link to see what I mean.

EDIT: To track an existing submodule project at a branch, follow VonC's instructions here instead:

Git submodules: Specify a branch/tag


The other way to make your submodule to check out the branch is to go the .gitmodules file in the root folder and add the field branch in the module configuration as following:

branch = <branch-name-you-want-module-to-checkout>


As other people have said, the reason this happens is that the parent repo only contains a reference to (the SHA1 of) a specific commit in the submodule – it doesn't know anything about branches. This is how it should work: the branch that was at that commit may have moved forward (or backwards), and if the parent repo had referenced the branch then it could easily break when that happens.

However, especially if you are actively developing in both the parent repo and the submodule, detached HEAD state can be confusing and potentially dangerous. If you make commits in the submodule while it's in detached HEAD state, these become dangling and you can easily lose your work. (Dangling commits can usually be rescued using git reflog, but it's much better to avoid them in the first place.)

If you're like me, then most of the time if there is a branch in the submodule that points to the commit being checked out, you would rather check out that branch than be in detached HEAD state at the same commit. You can do this by adding the following alias to your gitconfig file:

[alias]
    submodule-checkout-branch = "!f() { git submodule -q foreach 'branch=$(git branch --no-column --format=\"%(refname:short)\" --points-at `git rev-parse HEAD` | grep -v \"HEAD detached\" | head -1); if [[ ! -z $branch && -z `git symbolic-ref --short -q HEAD` ]]; then git checkout -q \"$branch\"; fi'; }; f"

Now, after doing git submodule update you just need to call git submodule-checkout-branch, and any submodule that is checked out at a commit which has a branch pointing to it will check out that branch. If you don't often have multiple local branches all pointing to the same commit, then this will usually do what you want; if not, then at least it will ensure that any commits you do make go onto an actual branch instead of being left dangling.

Furthermore, if you have set up git to automatically update submodules on checkout (using git config --global submodule.recurse true, see this answer), you can make a post-checkout hook that calls this alias automatically:

$ cat .git/hooks/post-checkout 
#!/bin/sh
git submodule-checkout-branch

Then you don't need to call either git submodule update or git submodule-checkout-branch, just doing git checkout will update all submodules to their respective commits and check out the corresponding branches (if they exist).

참고URL : https://stackoverflow.com/questions/18770545/why-is-my-git-submodule-head-detached-from-master

반응형