developer tip

Git 서브 모듈을 추가 할 때 브랜치 / 태그를 어떻게 지정할 수 있습니까?

copycodes 2020. 9. 30. 11:04
반응형

Git 서브 모듈을 추가 할 때 브랜치 / 태그를 어떻게 지정할 수 있습니까?


어떻게 git submodule add -b작동합니까?

특정 분기가있는 하위 모듈을 추가하면 새 복제 저장소 (이후 git submodule update --init)가 분기 자체가 아닌 특정 커밋에있게됩니다 ( git status하위 모듈에서 "현재 분기에 없음"으로 표시됨).

나는에 대한 정보 찾을 수없는 .gitmodules.git/config, 서브 모듈의 지점 또는 특정 커밋에 대한을 어떻게 수행 망할 놈의 그림을 알아?

또한 분기 대신 태그를 지정할 수 있습니까?

버전 1.6.5.2를 사용하고 있습니다.


참고 : Git 1.8.2에는 분기 추적 기능이 추가되었습니다. 아래 답변 중 일부를 참조하십시오.


이것에 익숙해지는 것은 약간 혼란 스럽지만 서브 모듈은 브랜치에 없습니다. 당신이 말했듯이 그것들은 단지 서브 모듈 저장소의 특정 커밋에 대한 포인터 일뿐입니다.

즉, 다른 사람이 저장소를 체크 아웃하거나 코드를 가져 와서 git 하위 모듈을 업데이트하면 해당 특정 커밋에 하위 모듈이 체크 아웃됩니다.

프로젝트의 모든 사람이 동일한 커밋에서 하위 모듈을 가질 수 있기 때문에 자주 변경되지 않는 하위 모듈에 적합합니다.

하위 모듈을 특정 태그로 이동하려면 :

cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push

그런 다음 submodule_directory를 해당 태그로 변경하려는 다른 개발자가

git pull
git submodule update --init

git pull서브 모듈 디렉토리가 가리키는 변경 사항. git submodule update실제로 새 코드에 병합됩니다.


여기에 다른 답변의 대기업에 불과한 답변을 추가하고 싶지만 더 완벽 할 것이라고 생각합니다.

이 두 가지가 있으면 Git 하위 모듈이 있다는 것을 알고 있습니다.

  1. 다음 .gitmodules과 같은 항목이 있습니다.

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
    
  2. Git 리포지토리에 하위 모듈 개체 (이 예제에서는 SubmoduleTestRepo라고 함)가 있습니다. GitHub 는이를 "하위 모듈"개체로 표시합니다. 또는 git submodule status명령 줄에서 수행하십시오 . Git 하위 모듈 객체는 특별한 종류의 Git 객체이며 특정 커밋에 대한 SHA 정보를 보유합니다.

    를 할 때마다 git submodule update커밋의 콘텐츠로 서브 모듈을 채 웁니다. 의 정보 때문에 커밋을 찾을 위치를 알고 .gitmodules있습니다.

    이제 파일에 -b한 줄을 추가하면 .gitmodules됩니다. 따라서 동일한 예를 따르면 다음과 같습니다.

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
        branch = master
    

    참고 :.gitmodules 파일 에서 분기 이름 만 지원 되지만 SHA 및 TAG는 지원되지 않습니다! (그 대신 각 모듈의 브랜치 커밋은 " git add ."를 사용하여 추적하고 업데이트 할 수 있습니다 ( 예 :) git add ./SubmoduleTestRepo. .gitmodules매번 파일 을 변경할 필요가 없습니다. )

    서브 모듈 객체는 여전히 특정 커밋을 가리키고 있습니다. -b옵션이 구매 하는 유일한 것은 --remoteVogella의 답변에 따라 업데이트에 플래그를 추가하는 기능입니다 .

    git submodule update --remote
    

    서브 모듈이 가리키는 커밋에 서브 모듈의 내용을 채우는 대신 해당 커밋을 마스터 브랜치의 최신 커밋으로 대체 한 다음 해당 커밋으로 서브 모듈을 채 웁니다. 이것은 djacobs7 답변으로 두 단계로 수행 할 수 있습니다. 이제 서브 모듈 객체가 가리키는 커밋을 업데이트 했으므로 변경된 서브 모듈 객체를 Git 저장소에 커밋해야합니다.

    git submodule add -b브랜치로 모든 것을 최신 상태로 유지하는 마법 같은 방법이 아닙니다. .gitmodules파일 의 분기에 대한 정보를 추가 하고 채우기 전에 지정된 분기의 최신 커밋으로 하위 모듈 객체를 업데이트하는 옵션을 제공합니다.


(Git 2.22, 2019 년 2 분기 출시 git submodule set-branch --branch aBranch -- <submodule_path>)

참고 당신이 경우 기존의 서브 모듈 되지 않은 아직 지점을 추적 (다음을, 당신은 자식 1.8.2+이있는 경우 ) :

  • 상위 저장소가 하위 모듈이 이제 분기를 추적한다는 것을 알고 있는지 확인하십시오.

    cd /path/to/your/parent/repo
    git config -f .gitmodules submodule.<path>.branch <branch>
    
  • 서브 모듈이 실제로 해당 분기의 최신 버전인지 확인하십시오.

    cd path/to/your/submodule
    git checkout -b branch --track origin/branch
      # if the master branch already exist:
      git branch -u origin/master master
    

         ( "원산지"의 이름으로 되 REPO 상류 원격 서브 모듈.로부터 클로닝되었다 해당 서브 모듈을 표시 안에. 일반적으로, 그것이 '원점')
git remote -v

  • 상위 저장소에 하위 모듈의 새 상태를 기록하는 것을 잊지 마십시오.

    cd /path/to/your/parent/repo
    git add path/to/your/submodule
    git commit -m "Make submodule tracking a branch"
    
  • 해당 하위 모듈에 대한 후속 업데이트는 다음 --remote옵션 을 사용해야합니다 .

    # update your submodule
    # --remote will also fetch and ensure that
    # the latest commit from the branch is used
    git submodule update --remote
    
    # to avoid fetching use
    git submodule update --remote --no-fetch 
    

Note that with Git 2.10+ (Q3 2016), you can use '.' as a branch name:

The name of the branch is recorded as submodule.<name>.branch in .gitmodules for update --remote.
A special value of . is used to indicate that the name of the branch in the submodule should be the same name as the current branch in the current repository.


If you want to update all your submodules following a branch:

    git submodule update --recursive --remote

Note that the result, for each updated submodule, will almost always be a detached HEAD, as Dan Cameron note in his answer.

(Clintm notes in the comments that, if you run git submodule update --remote and the resulting sha1 is the same as the branch the submodule is currently on, it won't do anything and leave the submodule still "on that branch" and not in detached head state.)

To ensure the branch is actually checked out (and that won't modify the SHA1 of the special entry representing the submodule for the parent repo), he suggests:

git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git checkout $branch'

Each submodule will still reference the same SHA1, but if you do make new commits, you will be able to push them because they will be referenced by the branch you want the submodule to track.
After that push within a submodule, don't forget to go back to the parent repo, add, commit and push the new SHA1 for those modified submodules.

Note the use of $toplevel, recommended in the comments by Alexander Pogrebnyak.
$toplevel was introduced in git1.7.2 in May 2010: commit f030c96.

it contains the absolute path of the top level directory (where .gitmodules is).

dtmland adds in the comments:

The foreach script will fail to checkout submodules that are not following a branch.
However, this command gives you both:

 git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git checkout $branch' –

The same command but easier to read:

git submodule foreach -q --recursive \
    'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; \
     [ "$branch" = "" ] && \
     git checkout master || git checkout $branch' –

umläute refines dtmland's command with a simplified version in the comments:

git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

multiple lines:

git submodule foreach -q --recursive \
  'git checkout \
  $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

Git 1.8.2 added the possibility to track branches.

# add submodule to track master branch
git submodule add -b branch_name URL_to_Git_repo optional_directory_rename

# update your submodule
git submodule update --remote 

See also Git submodules


An example of how I use Git submodules.

  1. Create a new repository
  2. Then clone another repository as a submodule
  3. Then we have that submodule use a tag called V3.1.2
  4. And then we commit.

And that looks a little bit like this:

git init 
vi README
git add README
git commit 
git submodule add git://github.com/XXXXX/xxx.yyyy.git stm32_std_lib
git status

git submodule init
git submodule update

cd stm32_std_lib/
git reset --hard V3.1.2 
cd ..
git commit -a

git submodule status 

Maybe it helps (even though I use a tag and not a branch)?


In my experience switching branches in the superproject or future checkouts will still cause detached HEADs of submodules regardless if the submodule is properly added and tracked (i.e. @djacobs7 and @Johnny Z answers).

And instead of manually checking out the correct branch manually or through a script git submodule foreach can be used.

This will check the submodule config file for the branch property and checkout the set branch.

git submodule foreach -q --recursive 'branch="$(git config -f <path>.gitmodules submodule.$name.branch)"; git checkout $branch'


Git submodules are a little bit strange - they're always in "detached head" mode - they don't update to the latest commit on a branch like you might expect.

This does make some sense when you think about it, though. Let's say I create repository foo with submodule bar. I push my changes and tell you to check out commit a7402be from repository foo.

Then imagine that someone commits a change to repository bar before you can make your clone.

When you check out commit a7402be from repository foo, you expect to get the same code I pushed. That's why submodules don't update until you tell them to explicitly and then make a new commit.

Personally I think submodules are the most confusing part of Git. There are lots of places that can explain submodules better than I can. I recommend Pro Git by Scott Chacon.


To switch branch for a submodule (assuming you already have the submodule as part of the repository):

  • cd to root of your repository containing the submodules
  • Open .gitmodules for editing
  • Add line below path = ... and url = ... that says branch = your-branch, for each submodule; save file .gitmodules.
  • then without changing directory do $ git submodule update --remote

...this should pull in the latest commits on the specified branch, for each submodule thus modified.


I have this in my .gitconfig file. It is still a draft, but proved useful as of now. It helps me to always reattach the submodules to their branch.

[alias]

######################
#
#Submodules aliases
#
######################


#git sm-trackbranch : places all submodules on their respective branch specified in .gitmodules
#This works if submodules are configured to track a branch, i.e if .gitmodules looks like :
#[submodule "my-submodule"]
#   path = my-submodule
#   url = git@wherever.you.like/my-submodule.git
#   branch = my-branch
sm-trackbranch = "! git submodule foreach -q --recursive 'branch=\"$(git config -f $toplevel/.gitmodules submodule.$name.branch)\"; git checkout $branch'"

#sm-pullrebase :
# - pull --rebase on the master repo
# - sm-trackbranch on every submodule
# - pull --rebase on each submodule
#
# Important note :
#- have a clean master repo and subrepos before doing this !
#- this is *not* equivalent to getting the last committed 
#  master repo + its submodules: if some submodules are tracking branches 
#  that have evolved since the last commit in the master repo,
#  they will be using those more recent commits !
#
#  (Note : On the contrary, git submodule update will stick 
#to the last committed SHA1 in the master repo)
#
sm-pullrebase = "! git pull --rebase; git submodule update; git sm-trackbranch ; git submodule foreach 'git pull --rebase' "

# git sm-diff will diff the master repo *and* its submodules
sm-diff = "! git diff && git submodule foreach 'git diff' "

#git sm-push will ask to push also submodules
sm-push = push --recurse-submodules=on-demand

#git alias : list all aliases
#useful in order to learn git syntax
alias = "!git config -l | grep alias | cut -c 7-"

We use Quack to pull a specific module from another Git repository. We need to pull code without the whole code base of the provided repository - we need a very specific module / file from that huge repository and should be updated every time we run update.

So we achieved it in this way:

Create configuration

name: Project Name

modules:
  local/path:
    repository: https://github.com/<username>/<repo>.git
    path: repo/path
    branch: dev
  other/local/path/filename.txt:
    repository: https://github.com/<username>/<repo>.git
    hexsha: 9e3e9642cfea36f4ae216d27df100134920143b9
    path: repo/path/filename.txt

profiles:
  init:
    tasks: ['modules']

With the above configuration, it creates one directory from the provided GitHub repository as specified in first module configuration, and the other one is to pull and create a file from the given repository.

Other developers just need to run

$ quack

And it pulls the code from the above configurations.


The only effect of choosing a branch for a submodule is that, whenever you pass the --remote option in the git submodule update command line, Git will check out in detached HEAD mode (if the default --checkout behavior is selected) the latest commit of that selected remote branch.

You must be particularly careful when using this remote branch tracking feature for Git submodules if you work with shallow clones of submodules. The branch you choose for this purpose in submodule settings IS NOT the one that will be cloned during git submodule update --remote. If you pass also the --depth parameter and you do not instruct Git about which branch you want to clone -- and actually you cannot in the git submodule update command line!! -- , it will implicitly behave like explained in the git-clone(1) documentation for git clone --single-branch when the explicit --branch parameter is missing, and therefore it will clone the primary branch only.

With no surprise, after the clone stage performed by the git submodule update command, it will finally try to check out the latest commit for the remote branch you previously set up for the submodule, and, if this is not the primary one, it is not part of your local shallow clone, and therefore it will fail with

fatal: Needed a single revision

Unable to find current origin/NotThePrimaryBranch revision in submodule path 'mySubmodule'


git submodule add -b develop --name branch-name -- https://branch.git

참고URL : https://stackoverflow.com/questions/1777854/how-can-i-specify-a-branch-tag-when-adding-a-git-submodule

반응형