programing

Git Submodule HEAD가 마스터에서 분리되는 이유는 무엇입니까?

padding 2023. 7. 17. 20:43
반응형

Git Submodule HEAD가 마스터에서 분리되는 이유는 무엇입니까?

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

왜 이렇게 될까요?

항상 해야 하는 일:

git branch
git checkout master

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

편집:

유효한 솔루션은 @Simba 답변 참조

submodule.<name>.update변경할 내용입니다. 문서 - 기본값을 참조하십시오.
submodule.<name>.branch추적할 원격 분기 지정 - 기본값


이전 답변:

개인적으로 저는 시간이 지남에 따라 작동을 멈추고 여기서 제 답변확인할 수 있는 외부 링크로 향하는 답변을 싫어합니다. (질문이 중복되지 않는 한) - 다른 주제의 행 사이에서 주제를 다루지만 전체적으로 동일한 질문으로 향하는 답변: "저는 답변하지 않습니다. 문서를 읽으십시오."

이제 질문으로 돌아갑니다.왜 이렇게 될까요?

설명한 상황

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

서브모듈을 자주 사용하지 않거나 서브모듈로 시작한 지 얼마 되지 않은 경우가 일반적입니다.서브모듈의 헤드가 분리되는 시점에 우리 모두가 거기에 있었다는 제 이 옳다고 생각합니다.

  • 원인: 하위 모듈이 올바른 분기(기본 마스터)를 추적하지 않습니다.
    파일: 확인합니다.
$ 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>
  • 원인: 상위 보고서가 하위 모듈 분기를 추적하도록 구성되지 않았습니다.
    파일: 명령을 하여 새 .다음 두 가지 명령을 사용하여 새 하위 모듈을 추가하여 하위 모듈이 원격 분기를 추적하도록 합니다.
    • 먼저 리모컨을 추적하라고 합니다.<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>

일반적인 경우 위의 구성 문제 중 하나와 관련된 문제이기 때문에 지금쯤 이미 분리된 헤드를 수정했습니다.

분리된 헤드 고정 시.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>

하위 모듈을 분리된 헤드 상태로 전환할 수 있는 경우가 몇 가지 더 있지만, 이제 특정 케이스를 디버깅하는 방법을 조금 더 이해해 주시기 바랍니다.

git submodule --helpHEAD 분리는 다음의 기본 동작입니다.git submodule update --remote이는 하위 모듈에서 추적 중인 분기와 관련이 없습니다.

해결책만 원하는 사람은 2부로 바로 이동합니다.

이유

우리는 서브모듈이 무엇인지 이해해야 합니다.

하위 모듈은 현재 프로젝트에 다른 프로젝트를 포함하는 방법입니다.이러한 파일을 실제로 기본 프로젝트의 커밋 기록에 추가하는 것이 아니라 하위 모듈의 스냅샷(커밋)을 참조하여 추가하는 것입니다.

Book Pro Git의 서브모듈로 시작 섹션에서 인용

모듈이 sb를 대신해서 sbut sb module sbut sb sb module.DbConnector작업 디렉터리의 하위 디렉터리입니다. Git는 하위 모듈로 보고 사용자가 해당 디렉터리에 없을 때 해당 내용을 추적하지 않습니다.대신 Git는 이를 해당 저장소의 특정 커밋으로 봅니다.

레포의 모든 커밋은 해당 시점의 코드 스냅샷/상태입니다.그 당시 서브모듈의 상태도 결정론적이어야 합니다.이 커밋에서는 다른 레포의 마스터(또는 다른) 브랜치를 포함한다고 말할 수 없습니다.하위 모듈의 상태를 커밋 ID로 지정해야 합니다.

다른 저장소를 하위 모듈로 포함하는 것은 기본적으로

git clone uri://another-repo path/to/submodule
cd path/to/submodule
git checkout <commit-id>

# git submodule system will add the reference commit id but not the files

과 함께 할 때, 이고, 그리고 다른사서과함레사때당용할, 것그서을복이고할제듈브모,checkout지정된 커밋도 마찬가지입니다.

그리고 커밋 결과를 확인하면 HEAD가 분리됩니다.내 Git repo가 분리된 HEAD 상태에 들어간 이유는 무엇입니까?

해결책

하려면 하위모원분자기병다사다음용니합을면려를 합니다.--merge또는--rebase.

man git-submodule

--비공식적인

옵션은 업데이트 명령에 대해서만 유효합니다.슈퍼 프로젝트에 기록된 커밋을 하위 모듈의 현재 분기에 병합합니다.이 옵션을 지정하면 서브모듈의 HEAD가 분리되지 않습니다.

--기본값

슈퍼 프로젝트에 기록된 커밋을 기준으로 현재 분기를 다시 작성합니다.이 옵션을 지정하면 서브모듈의 HEAD가 분리되지 않습니다.

하위 모듈이 이미 분리된 경우 다음 2가지 솔루션을 사용하기 전에 분리된 상태를 수정합니다.

cd path/to/submodule
# Assuming you're tracking the 'master' in the submodule
git checkout master

솔루션 1: 명령줄 옵션 사용

# cd back to project root
git submodule update --remote --merge
# or
git submodule update --remote --rebase

권장 별칭:

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

# do submodule update with
git supdate

솔루션 2: 구성 파일에 옵션 추가

입니다.gitmodule설별파일을 .submodule.$name.updatemerge또는rebase그것은 기본적으로 당신이 할 수 있다는 것을 의미합니다.git submodule update --remote하지 --merge또는--rebase명시적이지만 구성 파일에서 자동으로 읽습니다.

의 기본 에 대한 입니다..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

또는 명령줄을 통해 구성합니다.

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

다른이들

추가branch할 수 있습니다..gitmodule서브모듈의 분리 동작과는 전혀 관련이 없습니다. 이상 사용되지 .mkungla 오래대틀답리쓸없모습다니가나거의은된▁the없다습니m▁from▁old.

추적할 분기를 지정할 필요가 없습니다. origin/master추적할 기본 분기입니다.

--원격의

슈퍼 프로젝트의 기록된 SHA-1을 사용하여 하위 모듈을 업데이트하는 대신 하위 모듈의 원격 추적 분기 상태를 사용합니다.은 지점의입니다.branch.<name>.remote), 은 , 로 설정합니다origin된 기본값은 사된원기본은입니다.master.

레퍼런스

항상 분리하는 것에 싫증이 나서 셸 스크립트를 사용하여 모든 모듈을 구성합니다.모든 서브모듈이 켜져 있는 것 같습니다.master스크립트는 다음과 같습니다.

#!/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 

상위 모듈에서 실행

여기에서 제 답변을 확인하십시오. Git 하위 모듈: 분기/태그 지정

원하는 경우 수동으로 "modules = master" 줄을 .gitmodules 파일에 추가할 수 있습니다.링크를 읽어보면 무슨 뜻인지 알 수 있습니다.

편집: 분기의 기존 하위 모듈 프로젝트를 추적하려면 대신 VonC의 지침을 따르십시오.

Git 하위 모듈:분기/태그 지정

분기를 체크아웃하기 위해 당신의 서브모듈을 만드는 다른 방법은.gitmodules을 저장하고 합니다.branch다음과 같이 모듈 구성:

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

다른 사람들이 말했듯이, 이러한 현상이 발생하는 이유는 상위 레포가 하위 모듈의 특정 커밋에 대한 참조(SHA1)만 포함하고 있기 때문입니다. 하위 모듈은 분기에 대해 전혀 알지 못합니다.이렇게 해야 합니다. 즉, 해당 커밋에 있던 분기가 앞으로(또는 뒤로) 이동했을 수 있으며, 상위 레포가 분기를 참조했다면 이러한 경우 쉽게 중단될 수 있습니다.

에서 적극적으로 을 하고 하만당지, 히특이 parent repo와 submodule 모두으로적면적있다개발고하극서에신▁however,▁youod▁rep▁developing▁in면ule있다▁both▁the▁es,o▁the고uleo▁are▁actively▁reppecially▁if,▁parent하발개.detached HEAD상태는 혼란스럽고 잠재적으로 위험할 수 있습니다. 동안 커밋이 합니다.detached HEADstate,당신의 을 잃을 수 ( 상태, 은매되게고당잃일흔수있다을습니을신의당다게쉽구들리는수있니습될.)를 될 수 .)를 사용하여 구조될 수 .git reflog하지만 애초에 그들을 피하는 것이 훨씬 낫습니다.)

저와 같은 경우, 체크아웃되는 커밋을 가리키는 하위 모듈에 분기가 있는 경우 대부분 동일한 커밋에서 분리된 HEAD 상태에 있는 것보다 해당 분기를 체크아웃합니다.다음 별칭을 에 추가하여 이 작업을 수행할 수 있습니다.gitconfig파일 이름:

[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"

자를 한 에 한을 합니다.git submodule update당신은 그냥 전화하면 됩니다.git submodule-checkout-branch분기가 지정된 커밋에서 체크아웃된 하위 모듈은 해당 분기를 체크아웃합니다.여러 개의 로컬 분기가 모두 동일한 커밋을 가리키지 않는 경우, 일반적으로 이 작업은 원하는 대로 수행됩니다. 그렇지 않은 경우에는 적어도 모든 커밋을 중단하지 않고 실제 분기로 이동할 수 있습니다.

체크아웃 시으로 업데이트하도록 (「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」를 사용합니다.git config --global submodule.recurse true답변 참조), 이 별칭을 자동으로 호출하는 사후 후크를 만들 수 있습니다.

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

그럼 당신도 전화할 필요가 없습니다.git submodule update또는git submodule-checkout-branch 막는하기git checkout에서는 모든 하위 모듈을 해당 커밋으로 업데이트하고 해당 분기(존재하는 경우)를 확인합니다.

가장 간단한 솔루션은 다음과 같습니다.

git clone --recursive git@github.com:name/repo.git

그런 다음 repo 디렉토리에 cd를 넣고 다음을 수행합니다.

git submodule update --init
git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'
git config --global status.submoduleSummary true

추가 판독치: Git 하위 모듈 모범 사례.

저는 또한 아직 git의 내부를 파악하고 있으며, 지금까지 이것을 파악했습니다.

  1. HEAD는 .git/ 디렉토리에 있는 파일로 일반적으로 다음과 같습니다.
% cat .git/HEAD
ref: refs/heads/master
  1. refs/heads/master는 일반적으로 최신 커밋의 해시 값을 가진 파일입니다.
% cat .git/refs/heads/master 
cbf01a8e629e8d884888f19ac203fa037acd901f
  1. 마스터보다 앞선 원격 분기를 체크아웃하면 HEAD 파일이 업데이트되어 원격 마스터의 최신 커밋 해시가 포함될 수 있습니다.
% cat .git/HEAD
8e2c815f83231f85f067f19ed49723fd1dc023b7

이를 분리 HEAD라고 합니다.원격 마스터가 로컬 마스터보다 앞서 있습니다.서브모듈 --리모트 myrepo를 실행하여 서브모듈의 최신 커밋을 가져오면 기본적으로 체크아웃이 수행되어 HEAD가 업데이트됩니다.현재 지점장이 뒤에 있기 때문에 HEAD는 현재 지점에서 '분리'됩니다.

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

반응형