Bir git alt modülünün alt modülünü nasıl kaldırabilirim (tüm kodu çekirdeğe geri getirebilirim)?
"En iyi prosedür" de olduğu gibi "nasıl" yapmalıyım ...
Bir git alt modülünün alt modülünü nasıl kaldırabilirim (tüm kodu çekirdeğe geri getirebilirim)?
"En iyi prosedür" de olduğu gibi "nasıl" yapmalıyım ...
Yanıtlar:
İstediğiniz tek şey alt modül kodunuzu ana depoya koymaksa, alt modülü kaldırmanız ve dosyaları ana repoya yeniden eklemeniz yeterlidir:
git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash)
git rm .gitmodules # if you have more than one submodules,
# you need to edit this file instead of deleting!
rm -rf submodule_path/.git # make sure you have backup!!
git add submodule_path # will add files instead of commit reference
git commit -m "remove submodule"
Alt modülün geçmişini de korumak istiyorsanız, küçük bir numara yapabilirsiniz: alt modülün ana depoya "birleştirilmesi", böylece sonuç, daha önce olduğu gibi aynı olur, ancak alt modül dosyaları artık ana veri havuzu.
Ana modülde aşağıdakileri yapmanız gerekir:
# Fetch the submodule commits into the main repository
git remote add submodule_origin git://url/to/submodule/origin
git fetch submodule_origin
# Start a fake merge (won't change any files, won't commit anything)
git merge -s ours --no-commit submodule_origin/master
# Do the same as in the first solution
git rm --cached submodule_path # delete reference to submodule HEAD
git rm .gitmodules # if you have more than one submodules,
# you need to edit this file instead of deleting!
rm -rf submodule_path/.git # make sure you have backup!!
git add submodule_path # will add files instead of commit reference
# Commit and cleanup
git commit -m "removed submodule"
git remote rm submodule_origin
Ortaya çıkan depo biraz garip görünecek: birden fazla ilk taahhüt olacak. Ancak git için herhangi bir soruna neden olmaz.
Bu ikinci çözümde, başlangıçta alt modüllerde bulunan dosyalar üzerinde git blame veya git log'u çalıştırabilmeniz büyük bir avantaja sahip olacaksınız. Aslında burada yaptığınız şey bir havuzdaki birçok dosyayı yeniden adlandırmaktır ve git bunu otomatik olarak algılamalıdır. Git günlüğü ile ilgili hala sorun yaşıyorsanız, yeniden adlandırma / kopyalama algılamayı daha iyi yapan bazı seçenekleri (--follow, -M, -C) deneyin.
git merge
her dosya için (birleştirme işleminin iki “tarafından” birinde) bir "önceki işlem" uygulanmasını sağlar.
mkdir foo && git mv !(foo) foo && git commit
.
--allow-unrelated-histories
Ben bir daha almak için sahte birleştirme birleştirme zorlamak için eklemek gerekiyordu fatal: refusing to merge unrelated histories
, daha burada: github.com/git/git/blob/master/Documentation/RelNotes/…
Yana Git 1.8.5 (2013 Nov ) ( altmodülün tarihini tutmadan ):
mv yoursubmodule yoursubmodule_tmp
git submodule deinit yourSubmodule
git rm yourSubmodule
mv yoursubmodule_tmp yoursubmodule
git add yoursubmodule
Bu:
deinit
dolayısıyla mv
ilkini ),.gitmodules
sizin için temizler ( rm
),rm
.Alt modülün kaldırılması tamamlandığında ( deinit
ve git rm
), klasörü orijinal adına geri döndürebilir ve normal bir klasör olarak git repo'ya ekleyebilirsiniz.
Not: alt modül eski bir Git (<1.8) tarafından oluşturulduysa, Simon East tarafından yorumlandığı.git
gibi alt modülün içindeki iç içe geçmiş klasörü kaldırmanız gerekebilir
Eğer altmodülün geçmişini tutmak gerekiyorsa, bkz jsears 'ın cevabı hangi kullanımları git filter-branch
.
deinit
yalnız, çalışan ağacı alt modülünüzden temizlediniz mi?
Tüm dosya geçmişini korurken, bir alt modülü basit bir dizine çevirecek bir komut dosyası oluşturdum. git log --follow <file>
Diğer çözümlerin yaşadığı sorunlardan muzdarip değildir . Aynı zamanda tüm işleri sizin için yapan çok kolay tek satırlık bir çağrıdır. G'luck.
" Bir alt modülün ana depoya entegre edilmesi " adlı blog yazısında açıklanan Lucas Jenß'in mükemmel çalışmasına dayanıyor , ancak tüm süreci otomatikleştiriyor ve birkaç köşe vakasını temizliyor.
En son kod, https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite adresindeki github'daki hata düzeltmeleriyle korunacak , ancak uygun stackoverflow yanıt protokolü adına aşağıdaki bütün çözüm.
Kullanımı:
$ git-submodule-rewrite <submodule-name>
Git-alt modülü-yeniden yazın:
#!/usr/bin/env bash
# This script builds on the excellent work by Lucas Jenß, described in his blog
# post "Integrating a submodule into the parent repository", but automates the
# entire process and cleans up a few other corner cases.
# https://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html
function usage(){
echo "Merge a submodule into a repo, retaining file history."
echo "Usage: $0 <submodule-name>"
echo ""
echo "options:"
echo " -h, --help Print this message"
echo " -v, --verbose Display verbose output"
}
function abort {
echo "$(tput setaf 1)$1$(tput sgr0)"
exit 1
}
function request_confirmation {
read -p "$(tput setaf 4)$1 (y/n) $(tput sgr0)"
[ "$REPLY" == "y" ] || abort "Aborted!"
}
function warn() {
cat << EOF
This script will convert your "${sub}" git submodule into
a simple subdirectory in the parent repository while retaining all
contents and file history.
The script will:
* delete the ${sub} submodule configuration from .gitmodules and
.git/config and commit it.
* rewrite the entire history of the ${sub} submodule so that all
paths are prefixed by ${path}.
This ensures that git log will correctly follow the original file
history.
* merge the submodule into its parent repository and commit it.
NOTE: This script might completely garble your repository, so PLEASE apply
this only to a fresh clone of the repository where it does not matter if
the repo is destroyed. It would be wise to keep a backup clone of your
repository, so that you can reconstitute it if need be. You have been
warned. Use at your own risk.
EOF
request_confirmation "Do you want to proceed?"
}
function git_version_lte() {
OP_VERSION=$(printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4))
GIT_VERSION=$(git version)
GIT_VERSION=$(printf "%03d%03d%03d%03d" $(echo "${GIT_VERSION#git version}" | tr '.' '\n' | head -n 4))
echo -e "${GIT_VERSION}\n${OP_VERSION}" | sort | head -n1
[ ${OP_VERSION} -le ${GIT_VERSION} ]
}
function main() {
warn
if [ "${verbose}" == "true" ]; then
set -x
fi
# Remove submodule and commit
git config -f .gitmodules --remove-section "submodule.${sub}"
if git config -f .git/config --get "submodule.${sub}.url"; then
git config -f .git/config --remove-section "submodule.${sub}"
fi
rm -rf "${path}"
git add -A .
git commit -m "Remove submodule ${sub}"
rm -rf ".git/modules/${sub}"
# Rewrite submodule history
local tmpdir="$(mktemp -d -t submodule-rewrite-XXXXXX)"
git clone "${url}" "${tmpdir}"
pushd "${tmpdir}"
local tab="$(printf '\t')"
local filter="git ls-files -s | sed \"s/${tab}/${tab}${path}\//\" | GIT_INDEX_FILE=\${GIT_INDEX_FILE}.new git update-index --index-info && mv \${GIT_INDEX_FILE}.new \${GIT_INDEX_FILE}"
git filter-branch --index-filter "${filter}" HEAD
popd
# Merge in rewritten submodule history
git remote add "${sub}" "${tmpdir}"
git fetch "${sub}"
if git_version_lte 2.8.4
then
# Previous to git 2.9.0 the parameter would yield an error
ALLOW_UNRELATED_HISTORIES=""
else
# From git 2.9.0 this parameter is required
ALLOW_UNRELATED_HISTORIES="--allow-unrelated-histories"
fi
git merge -s ours --no-commit ${ALLOW_UNRELATED_HISTORIES} "${sub}/master"
rm -rf tmpdir
# Add submodule content
git clone "${url}" "${path}"
rm -rf "${path}/.git"
git add "${path}"
git commit -m "Merge submodule contents for ${sub}"
git config -f .git/config --remove-section "remote.${sub}"
set +x
echo "$(tput setaf 2)Submodule merge complete. Push changes after review.$(tput sgr0)"
}
set -euo pipefail
declare verbose=false
while [ $# -gt 0 ]; do
case "$1" in
(-h|--help)
usage
exit 0
;;
(-v|--verbose)
verbose=true
;;
(*)
break
;;
esac
shift
done
declare sub="${1:-}"
if [ -z "${sub}" ]; then
>&2 echo "Error: No submodule specified"
usage
exit 1
fi
shift
if [ -n "${1:-}" ]; then
>&2 echo "Error: Unknown option: ${1:-}"
usage
exit 1
fi
if ! [ -d ".git" ]; then
>&2 echo "Error: No git repository found. Must be run from the root of a git repository"
usage
exit 1
fi
declare path="$(git config -f .gitmodules --get "submodule.${sub}.path")"
declare url="$(git config -f .gitmodules --get "submodule.${sub}.url")"
if [ -z "${path}" ]; then
>&2 echo "Error: Submodule not found: ${sub}"
usage
exit 1
fi
if ! [ -d "${path}" ]; then
>&2 echo "Error: Submodule path not found: ${path}"
usage
exit 1
fi
main
curl https://raw.githubusercontent.com/jeremysears/scripts/master/bin/git-submodule-rewrite > git-submodule-rewrite.sh
ve./git-submodule-rewrite.sh <submodule-name>
git rm --cached the_submodule_path
.gitmodules
dosyadan kaldırın veya tek alt modülse, dosyayı kaldırın.git add the_submodule_path
Daha kolay bir yol bulamadım. git commit -a
Damak tadına göre 3-5'i tek adımda sıkıştırabilirsiniz .
.gitmodules
yerine olmamalı mı .submodules
?
.gitmodules
değil.submodules
.git
önce git add
alt modül klasörü üzerinde çalışmak için alt modül dizini kaldırmak zorunda
Burada bir sürü cevap var ama hepsi aşırı karmaşık görünüyor ve muhtemelen ne istediğinizi yapmıyor. Eminim çoğu insan tarihini korumak ister.
Bu örnek için ana repo olacak git@site.com:main/main.git
ve alt modül repo olacak git@site.com:main/child.git
. Bu, alt modülün üst repo kök dizininde bulunduğunu varsayar. Talimatları gerektiği gibi ayarlayın.
Üst repoyu klonlayarak ve eski alt modülü kaldırarak başlayın.
git clone git@site.com:main/main.git
git submodule deinit child
git rm child
git add --all
git commit -m "remove child submodule"
Şimdi çocuk repolarını ana repoya akıntıya ekleyeceğiz.
git remote add upstream git@site.com:main/child.git
git fetch upstream
git checkout -b merge-prep upstream/master
Sonraki adım, birleştirme hazırlığı dalındaki dosyaları alt modülün bulunduğu konuma taşımak istediğinizi varsayar, ancak dosya yolunu değiştirerek konumu kolayca değiştirebilirsiniz.
mkdir child
.git klasörü dışındaki tüm klasör ve dosyaları alt klasöre taşıyın.
git add --all
git commit -m "merge prep"
Artık dosyalarınızı ana dalda birleştirebilirsiniz.
git checkout master
git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required
Etrafınıza bakın ve koşmadan önce her şeyin iyi göründüğünden emin olun git push
Şimdi hatırlamanız gereken tek şey git günlüğünün varsayılan olarak taşınan dosyaları takip etmemesi, ancak çalıştırarak dosyalarınızın git log --follow filename
tam geçmişini görebilirsiniz.
git merge merge-prep
ve hatayı aldım fatal: refusing to merge unrelated histories
. Geçici çözüm şudur: git merge --allow-unrelated-histories merge-prep
.
child
dizine getirmenin herhangi bir yolu var mı , bu yüzden onları daha sonra taşımak zorunda değil misiniz? Ben bir alt modül ve ana repo aynı dosya isimleri var ... bu yüzden iki dosyayı bir araya getirmek için çalışıyor çünkü ben sadece bir birleştirme çakışması olsun.
Bize, 2 proje için, birbirlerinden ayrılmalarının hiçbir anlamı olmayacak şekilde birleştirilen 2 havuz için 2 depo oluşturduk, bu yüzden onları birleştirdik.
Her biri ana dalların nasıl birleştirileceğini göstereceğim ve sonra bunu sahip olduğunuz her dal için nasıl genişletebileceğinizi açıklayacağım, umarım size yardımcı olur.
Alt modülün çalışmasını sağladıysanız ve bunu yerinde bir dizine dönüştürmek istiyorsanız şunları yapabilirsiniz:
git clone project_uri project_name
Burada çalışmak için temiz bir klon yapıyoruz. Bu işlem için alt modülleri başlatmanız veya güncellemeniz gerekmez, bu yüzden atlayın.
cd project_name
vim .gitmodules
Değiştirmeyi .gitmodules
planladığınız alt modülü kaldırmak için favori düzenleyicinizle (veya Vim) düzenleyin. Kaldırmanız gereken çizgiler şöyle görünmelidir:
[submodule "lib/asi-http-request"]
path = lib/asi-http-request
url = https://github.com/pokeb/asi-http-request.git
Dosyayı kaydettikten sonra,
git rm --cached directory_of_submodule
git commit -am "Removed submodule_name as submodule"
rm -rf directory_of_submodule
Burada, diğer repoyu projeye yerinde getirebilmemiz için alt modül ilişkisini tamamen kaldırıyoruz.
git remote add -f submodule_origin submodule_uri
git fetch submodel_origin/master
Burada birleştirmek için alt modül deposunu getiriyoruz.
git merge -s ours --no-commit submodule_origin/master
Burada 2 havuzun birleştirme işlemine başlıyoruz, ancak taahhütten önce duruyoruz.
git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master
Burada alt modül içindeki master içeriğini bir dizin adı önekini eklemeden önceki dizine gönderiyoruz
git commit -am "submodule_name is now part of main project"
Burada, birleşmedeki değişikliklerin bir taahhüdünü yaparak prosedürü tamamlıyoruz.
Bunu bitirdikten sonra, itebilir ve birleştirmek için başka bir dalla yeniden başlayabilirsiniz, sadece deponuzdaki değişiklikleri alacak ve birleştirme ve okuma ağacı işlemlerinde getirdiğiniz dalı değiştirecek olan şubeye göz atın.
directory_of_submodule
git log original_path_of_file_in_submodule
alt modül dosyası olsa bile dosya için git repo (yani artık dosya sisteminde artık yok) kayıtlı yolu yaparak birleştirilmiş alt modül dosyalarının geçmişini almak mümkün olduğunu düşünüyorum şimdi yaşıyorsubmodule_path/new_path_of_file
Bulduğum en iyi cevap burada:
http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html
Bu makalede, prosedür çok iyi açıklanmaktadır.
İşte @ gyim'in cevabının biraz geliştirilmiş bir versiyonu (IMHO). Ana çalışma kopyasında bir sürü tehlikeli değişiklik yapıyor, burada ayrı klonlar üzerinde çalışmanın ve sonunda onları birleştirmenin çok daha kolay olduğunu düşünüyorum.
Ayrı bir dizinde (hataların temizlenmesini ve tekrar denenmesini kolaylaştırmak için) hem üst repoya hem de alt rapora göz atın.
git clone ../main_repo main.tmp
git clone ../main_repo/sub_repo sub.tmp
Önce tüm dosyaları istediğiniz alt dizine taşımak için alt raporu düzenleyin
cd sub.tmp
mkdir sub_repo_path
git mv `ls | grep -v sub_repo_path` sub_repo_path/
git commit -m "Moved entire subrepo into sub_repo_path"
BAŞKANI not edin
SUBREPO_HEAD=`git reflog | awk '{ print $1; exit; }'`
Şimdi alt depoyu ana depodan kaldırın
cd ../main.tmp
rmdir sub_repo_path
vi .gitmodules # remove config for submodule
git add -A
git commit -m "Removed submodule sub_repo_path in preparation for merge"
Ve son olarak onları birleştir
git fetch ../sub.tmp
# remove --allow-unrelated-histories if using git older than 2.9.0
git merge --allow-unrelated-histories $SUBREPO_HEAD
Ve bitti! Güvenli ve sihirsiz.
subrepo
şeyler bulunan bir dizin içeriyorsa çalışır mı ?
git merge $SUBREPO_HEAD fatal: refusing to merge unrelated histories
kullanmalı mıyım git merge $SUBREPO_HEAD --allow-unrelated-histories
? Yoksa onsuz çalışmalı ve ben bir hata mı yaptım?
Ne zaman için
git rm [-r] --cached submodule_path
İadeler
fatal: pathspec 'emr/normalizers/' did not match any files
Bağlam: rm -r .git*
Onları eklediğim ana projede alt modüle edilmeleri gerektiğini fark etmeden önce alt modül klasörlerimde yaptım . Bazılarını de-modüle ederken yukarıdaki hatayı aldım, ama hepsini değil. Her neyse, onları çalıştırarak sabitledim, (elbette, sonra rm -r .git*
)
mv submodule_path submodule_path.temp
git add -A .
git commit -m "De-submodulization phase 1/2"
mv submodule_path.temp submodule_path
git add -A .
git commit -m "De-submodulization phase 2/2"
Bunun geçmişi korumadığını unutmayın.
VonC'nin cevabına dayanarak , bunu yapan basit bir bash betiği oluşturdum. add
Sonunda joker kullanmak aksi takdirde önceki geri alır sahiptir rm
altmodülün kendisi için. Alt modül dizininin içeriğini eklemek ve dizinin kendisiniadd
komutta .
Adlı bir dosyada git-integrate-submodule
:
#!/usr/bin/env bash
mv "$1" "${1}_"
git submodule deinit "$1"
git rm "$1"
mv "${1}_" "$1"
git add "$1/**"
(Ayrıca?) Alt modülünden yerel taahhüt verileri almak için daha uygun buldum, çünkü aksi takdirde onları kaybedersiniz. (O uzaktan kumandaya erişemediğim için onları zorlayamadım). Bu yüzden remote_origin2 olarak alt modül / .git ekledim, söz konusu daldan getirildi ve birleştirildi. Henüz git ile yeterince tanıdık olmadığım için hala orijinallik olarak alt modülün gerekli olup olmadığından emin değilim.
İşte en iyi ve en basit bulduğum şey.
Alt modül deposunda, HEAD'den ana repo ile birleştirmek istiyorsunuz:
git checkout -b "mergeMe"
mkdir "foo/bar/myLib/"
(ana repodaki dosyaları istediğiniz yere özdeş yol)git mv * "foo/bar/myLib/"
(hepsini yola taşı)git commit -m "ready to merge into main"
Alt modülü çıkardıktan ve "foo / bar / myLib" yolunu temizledikten sonra ana depoya dönün:
git merge --allow-unrelated-histories SubmoduleOriginRemote/mergeMe
patlama bitti
Geçmişler korunmuş
telaşa gerek yok
Bunun diğer bazı cevaplarla neredeyse aynı olduğunu unutmayın. Ancak bu, kendi alt modül deponuz olduğunu varsayar. Ayrıca bu, alt modül için gelecekteki yukarı akış değişikliklerini almayı kolaylaştırır.
git submodule deinit
, aşağıdaki cevabımı