Подмодули Git: укажите ветвь / тег

как git submodule add -b работы?

после добавления подмодуля с определенной ветвью, новое клонированное РЕПО (после git submodule update --init) будет при определенной фиксации, а не сама ветвь (git status в подмодуле отображается "в настоящее время не на какой-либо ветке").

Я не могу найти никакой информации о .gitmodules или .git/config о ветви подмодуля или какой-либо конкретной фиксации, так как git выясняет это?

кроме того, можно ли указать тег вместо бранч?

PS: я использую 1.6.5.2.

11 ответов


Примечание: 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

git pull изменения, которые фиксируют точки каталога подмодулей. git submodule update фактически сливается в новом коде.


Я хотел бы добавить ответ здесь, который на самом деле является просто конгломератом других ответов, но я думаю, что он может быть более полным.

вы знаете, что у вас есть подмодуль git, когда у вас есть эти две вещи.

1) Ваш .gitmodules имеется запись Вот так:

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

2) у вас есть объект подмодуля (названный SubmoduleTestRepo в этом примере) в вашем репозитории git. Github показывает их как "подмодуль" объекты. Или git submodule status из командной строки. Объекты подмодуля Git-это особый вид объекта git, и они содержат информацию SHA для определенной фиксации.

всякий раз, когда вы делаете git submodule update, он заполнит ваш подмодуль содержимым из фиксации. Он знает, где найти фиксацию из-за информации в .gitmodules.

теперь все -b делает, это добавить одну строку в ваш . Поэтому, следуя тому же примеру, это будет выглядеть так:

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

EDIT: только имя ветви поддерживается выше, а не SHA или TAG.

объект подмодуля по-прежнему указывает на определенную фиксацию. Единственное, что -b опция покупает вам возможность добавить --remote флаг для вашего обновления в соответствии с ответом Vogella:

git submodule update --remote

вместо заполнения содержимого подмодуля фиксацией, на которую указывает подмодуль, он заменяет эту фиксацию последней фиксацией в главной ветви, а затем заполняет подмодуль этой фиксацией. Это может быть сделано в два шага по djacobs7 ответ. Поскольку теперь вы обновили фиксацию, на которую указывает объект подмодуля, вы должны зафиксировать измененный объект подмодуля в своем репозитории git.

git submodule add -b это не какой-то волшебный способ держать все в курсе с веткой. Это просто добавляет информацию о ветке в .gitmodules file и дает вам возможность обновить объект подмодуля до последней фиксации указанной ветви перед ее заполнением.


отметим, что если у вас существующей подмодуль, который не отслеживание ветки еще, тогда (если у вас есть git 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
    

         (с "происхождением" бытия имя вышестоящий репозиторий подмодуль был клонирован.
         А git remote -v внутри этого подмодуля будет отображаться. Обычно это 'origin')

  • не забудьте записать новое состояние вашего подмодуля в Родительском РЕПО:

    cd /path/to/your/parent/repo
    git add path/to/your/submodule
    git commit -m "Make submodule tracking a branch"
    
  • последующее обновление для этого подмодуля должно будет использовать :

    # 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 
    

обратите внимание, что с Git 2.10+ (Q3 2016), вы можете использовать'.' как название филиала:

название филиала записывается как submodule.<name>.branch на .gitmodules на update --remote.
особое значение . используется для указания того, что имя ветви в подмодуле должно совпадать с именем текущей ветви в текущем репозитории.


если вы хотите обновить все свои подмодули после ветви:

    git submodule update --recursive --remote

обратите внимание, что результат, для каждого обновленного субмодуль, будет почти всегда отрезанная голова, as Дэн Камерон примечание в ответ.

( Clintm Примечания в комментариях, что если git submodule update --remote и результирующий sha1 такой же, как ветвь, на которой в настоящее время находится подмодуль, он ничего не сделает и оставить подмодуль еще "на той ветке", а не в обособленном головном состоянии.)

чтобы убедиться, что ветка фактически проверена (и это не изменит SHA1 специальная запись представляя подмодуль для родительского РЕПО), он предлагает:

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

каждый подмодуль будет по-прежнему ссылаться на тот же SHA1, но если вы сделаете новые коммиты, вы сможете нажать их, потому что они будут ссылаться на ветку, которую вы хотите подмодуль для отслеживания.
После этого нажмите в подмодуле, не забудьте вернуться к родительскому РЕПО, добавить, зафиксировать и нажать новый SHA1 для этих измененных подмодулей.

обратите внимание на использование $toplevel, рекомендовано в комментариях by Александр Погребняк.
$toplevel был представлен в git1.7.2 в мае 2010 года:совершить f030c96.

он содержит абсолютный путь каталога верхнего уровня (где .gitmodules is).

dtmland добавляет в комментариях:

скрипт foreach не сможет проверить подмодули, которые не следуют за ветвью.
Однако эта команда дает вам оба:

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

та же команда, но легче читать:

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

umläute уточняется dtmlandкоманда с упрощенной версией в комментариях:

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

несколько строк:

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

в Git 1.8.2 добавлена возможность отслеживать ветки.

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 

см. также в Git подмодулей


пример использования подмодулей git.

  1. создает новое РЕПО
  2. затем клонирует другое РЕПО как подмодуль
  3. затем мы видим, что субмодуль использовать тег под названием "В3".1.2
  4. и тогда мы совершаем

и это выглядит немного так:

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 

может это поможет? (даже ты я использую бирку, а не ветку)


по моему опыту переключение ветвей в суперпроекте или будущих проверках все равно приведет к отсоединению головок подмодулей независимо от того, правильно ли добавлен и отслежен подмодуль (т. е. ответы @djacobs7 и @Johnny Z).

и вместо того, чтобы вручную проверять правильную ветку вручную или через скрипт git подмодуль foreach можно использовать.

это проверит файл конфигурации подмодуля для свойства branch и проверит набор отделение.

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


подмодули git немного странные - они всегда находятся в режиме" отсоединенной головы " - они не обновляются до последней фиксации в ветке, Как вы могли бы ожидать.

в этом есть смысл, когда вы думаете об этом, хотя. Допустим, я создаю репозиторий foo с подмодулем bar. Я нажимаю свои изменения и говорю вам проверить commit a7402be из репозитория foo.

затем представьте, что кто-то совершает изменение в репо-баре, прежде чем вы сможете сделать клон.

когда вы проверяете commit a7402be из repo foo, вы ожидаете получить тот же код, который я нажал. Вот почему подмодули не обновляются, пока вы не скажете им явно, а затем не сделаете новую фиксацию.

лично я думаю, что подмодули-самая запутанная часть git. Есть много мест, которые могут объяснить подмодули лучше, чем я. Я рекомендую Pro Git Скотт Чакон.


У меня есть это в моем .файл gitconfig хранит настройки. Это все еще черновик, но уже доказал свою полезность. Это помогает мне всегда присоединять подмодули к их ветви.

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

чтобы переключить ветвь для подмодуля (предполагая, что у вас уже есть подмодуль как часть РЕПО):

  • cd к корню вашего РЕПО, содержащего подмодули
  • открыть .gitmodules для редактирования
  • добавить строку ниже path = ... и url = ... что говорит branch = your-branch, для каждого подмодуля; сохранить файл .gitmodules.
  • затем без изменения каталог $ git submodule update --remote

...это должно вытащить последние коммиты на указанном ветвь, для каждого подмодуля, модифицированного таким образом.


мы используем:кряк чтобы вытащить конкретный модуль из другого репозитория git. Нам нужно вытащить код без всей кодовой базы предоставленного репозитория - нам нужен очень конкретный модуль / файл из этого огромного репозитория и должен обновляться каждый раз, когда мы запускаем обновление.

таким образом, мы достигли таким образом,

создать конфигурацию

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']

с вышеуказанной конфигурацией он создает 1 каталог из предоставленного репозитория github, как указано в первом конфигурация модуля, а другой-вытащить и создать файл из данного РЕПО.

другим разработчикам просто нужно запустить

$ quack

и он вытягивает код из вышеуказанных конфигураций.


выбор ветви для подмодуля имеет единственный эффект, позволяя git checkout в отделенном головном состоянии (если по умолчанию --checkout поведение выбрано) последняя фиксация выбранной ветви при передаче на git submodule update командная строка.

обратите внимание, что ветку вы выбрали для этой цели в настройках субмодуль НЕТ тот, который будет клонирован в submodule update --remote. Как тонкое следствие, если вы проходите также и вы не указывайте git, какую ветку вы хотите клонировать -- !! и на самом деле вы не можете в командной строке команду git подмодуля обновление !! -- , он будет неявно вести себя так, как описано в git-clone(1) документы на git clone --single-branch с отсутствующим явным