Git 하위 모듈을 사용하고 있습니다. 서버에서 변경 사항을 가져온 후 여러 번 내 하위 모듈 헤드가 마스터 분기에서 분리됩니다.
왜 그런가요?
나는 항상해야합니다 :
git branch
git checkout master
하위 모듈이 항상 마스터 분기를 가리 키도록하려면 어떻게해야합니까?
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>
<branch>
. $ 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 상태로 전환 할 수있는 경우가 더 있지만 특정 사례를 디버깅하는 방법을 조금 더 이해하기를 바랍니다.
git submodule update --remote
. Simba의 답변을 살펴보십시오. 정답이라고 생각합니다.
branch
옵션 을 추가하는 것은 서브 모듈의 분리 된 동작과 전혀 관련.gitmodule
이 없습니다 . @mkungla의 이전 답변이 잘못되었거나 더 이상 사용되지 않습니다.
에서 git submodule --help
, HEAD가 분리하면 기본 동작 의 git submodule update --remote
.
먼저 추적 할 분기를 지정할 필요가 없습니다 . origin/master
추적 할 기본 분기입니다.
--먼
수퍼 프로젝트의 기록 된 SHA-1을 사용하여 서브 모듈을 업데이트하는 대신 서브 모듈의 원격 추적 브랜치 상태를 사용하십시오. 사용되는 리모컨은 지점의 리모컨 (
branch.<name>.remote
)이며 기본값은origin
입니다. 사용 된 원격 분기의 기본값은master
입니다.
그렇다면 왜 HEAD가 분리 update
됩니까? 이는 기본 모듈 업데이트 동작으로checkout
인해 발생합니다 .
--점검
서브 모듈에서 분리 된 HEAD 에서 수퍼 프로젝트에 기록 된 커밋 을 확인하십시오. 이것이 기본 동작 이며,이 옵션의 주된 용도는
submodule.$name.update
다른 값으로 설정 될 때 재정의 하는 것checkout
입니다.
이 이상한 업데이트 동작을 설명하려면 하위 모듈의 작동 방식을 이해해야합니까?
sbmodule
DbConnector
은 작업 디렉토리의 하위 디렉토리 이지만 Git 은 하위 디렉토리로 간주하고 해당 디렉토리에 없을 때 내용을 추적하지 않습니다. 대신 Git 은 해당 저장소 의 특정 커밋 으로 간주 합니다 .
메인 리포지토리 는 특정 시점 의 커밋 ID 에서 서브 모듈 의 상태를 추적합니다 . 따라서 모듈을 업데이트하면 커밋 ID를 새 것으로 업데이트합니다.
하위 모듈을 원격 지점과 자동으로 병합하려면 --merge
또는을 사용하십시오 --rebase
.
-병합
이 옵션은 update 명령 에만 유효합니다 . 수퍼 프로젝트에 기록 된 커밋을 서브 모듈의 현재 브랜치에 병합하십시오. 이 옵션을 지정하면 서브 모듈의 HEAD가 분리되지 않습니다 .
-리베이스
현재 브랜치를 수퍼 프로젝트에 기록 된 커밋으로 리베이스하십시오. 이 옵션을 지정하면 서브 모듈의 HEAD가 분리되지 않습니다 .
당신이해야 할 일은
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
만드는 옵션도 있습니다 --merge
또는 --rebase
의 기본 동작으로 git submodule update
설정하여, submodule.$name.update
에 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
git submodule --help
git submodule update --remote --merge
하고 하위 모듈을 분리 된 상태로 풀다운합니다. --rebase
같은 결과로 시도 했습니다.
cd
을 사용하여 하위 모듈을 특정 분기에 체크 아웃하십시오 git checkout master
.
git submodule foreach --recursive git checkout master
.
git submodule foreach --recursive git checkout master
. 그러나 자식이 항상 분리하지 못하게하려면 어떻게해야합니까? 각 하위 모듈에 대한 구성 옵션을 설정 하는 것은 옵션이 아닙니다!
git submodule update --remote --merge
하면 하위 모듈이 분리 된 HEAD 상태로 유지되지 않았지만 DID가 표시 한 것처럼 파일을 git submodule update
편집 한 후 실행 .gitmodule
하면 하위 모듈이 분리 된 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
부모 모듈에서 실행하십시오.
내 대답을 확인하십시오 : Git 하위 모듈 : 지점 / 태그 지정
원하는 경우 "branch = master"줄을 .gitmodules 파일에 수동으로 추가 할 수 있습니다. 의미를 알아 보려면 링크를 읽으십시오.
편집 : 지점에서 기존 서브 모듈 프로젝트를 추적하려면 대신 VonC의 지침을 따르십시오.
branch = master" line into your .gitmodule
전체 답변 과 마찬가지로 그 문제에 대한 답을 얻었습니다.
서브 모듈이 브랜치를 체크 아웃하게하는 다른 방법 .gitmodules
은 루트 폴더에있는 파일 로 이동하여 branch
다음과 같이 모듈 구성에 필드 를 추가하는 것입니다 .
branch = <branch-name-you-want-module-to-checkout>
branch = my_wanted_branch
. 그러나 git submodule update --remote
그것을 실행 하면 여전히 분리 된 헤드로 확인됩니다.
다른 사람들이 말했듯이, 이것이 발생하는 이유는 부모 저장소에 하위 모듈의 특정 커밋에 대한 참조 (SHA1) 만 포함하기 때문에 분기에 대해 아무것도 알지 못하기 때문입니다. 이것이 작동하는 방식입니다. 커밋에 있던 브랜치가 앞으로 (또는 뒤로) 움직일 수 있으며, 부모 리포지토리가 브랜치를 참조하면 브랜치가 발생할 때 쉽게 깨질 수 있습니다.
그러나 특히 상위 리포지토리와 하위 모듈에서 적극적으로 개발하는 경우 detached HEAD
상태가 혼란스럽고 잠재적으로 위험 할 수 있습니다. 서브 모듈이 커밋 된 detached HEAD
상태 에서 커밋을 수행하면 서브 모듈 이 매달려있어 작업을 쉽게 잃을 수 있습니다. (매달려 커밋은 일반적으로을 사용하여 구제 할 수 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을 설정 한 경우 ( git config --global submodule.recurse true
, this answer 참조 )이 별칭을 자동으로 호출하는 체크 아웃 후 후크를 만들 수 있습니다.
$ 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 서브 모듈 모범 사례 .