İlk birkaç düzine deneme-yanılma içeren 400'den fazla taahhüt içeren bir Git depomuz var. Bu taahhütleri birçoğunu tek bir taahhütte ezerek temizlemek istiyoruz. Doğal olarak, git-rebase gidilecek yol gibi görünüyor. Benim sorunum, birleştirme çakışmaları ile sonuçlanması ve bu çatışmaların çözülmesi kolay olmamasıdır. Neden herhangi bir çatışma olması gerektiğini anlamıyorum, çünkü sadece taahhütleri eziyorum (silme veya yeniden düzenleme değil). Büyük olasılıkla, bu git-rebase'in kabaklarını nasıl yaptığını tam olarak anlamadığımı gösteriyor.
İşte kullandığım komut dosyalarının değiştirilmiş bir sürümü:
repo_squash.sh (bu aslında çalıştırılan komut dosyasıdır):
rm -rf repo_squash
git clone repo repo_squash
cd repo_squash/
GIT_EDITOR=../repo_squash_helper.sh git rebase --strategy theirs -i bd6a09a484b8230d0810e6689cf08a24f26f287a
repo_squash_helper.sh (bu script sadece repo_squash.sh tarafından kullanılır):
if grep -q "pick " $1
then
# cp $1 ../repo_squash_history.txt
# emacs -nw $1
sed -f ../repo_squash_list.txt < $1 > $1.tmp
mv $1.tmp $1
else
if grep -q "initial import" $1
then
cp ../repo_squash_new_message1.txt $1
elif grep -q "fixing bad import" $1
then
cp ../repo_squash_new_message2.txt $1
else
emacs -nw $1
fi
fi
repo_squash_list.txt: (bu dosya sadece repo_squash_helper.sh tarafından kullanılır)
# Initial import
s/pick \(251a190\)/squash \1/g
# Leaving "Needed subdir" for now
# Fixing bad import
s/pick \(46c41d1\)/squash \1/g
s/pick \(5d7agf2\)/squash \1/g
s/pick \(3da63ed\)/squash \1/g
"Yeni mesaj" içeriğini hayal gücünüze bırakacağım. Başlangıçta, bunu "--strategy onların" seçeneği olmadan yaptım (yani, belgelerin doğru olduğunu anlarsam özyinelemeli, ancak hangi özyinelemeli stratejinin kullanıldığından emin değilim) ve aynı zamanda ' Çalışmıyor. Ayrıca, repo_squash_helper.sh içinde yorumlanmış kodu kullanarak, sed komut dosyasının üzerinde çalıştığı orijinal dosyayı kaydettiğimi ve bunu yapmak istediğim şeyi yaptığından emin olmak için sed komut dosyasını çalıştırdığımı belirtmeliyim ( öyleydi). Yine, neden bir çatışma olacağını bile bilmiyorum , bu yüzden hangi stratejinin kullanıldığı çok önemli değil gibi görünüyor. Herhangi bir tavsiye veya fikir yardımcı olacaktır, ama çoğunlukla sadece bu ezme çalışma almak istiyorum.
Jefromi ile yapılan tartışmalardan ek bilgilerle güncellendi:
Büyük "gerçek" veri havuzumuz üzerinde çalışmadan önce, bir test veri havuzunda benzer komut dosyaları kullandım. Çok basit bir havuzdu ve test temiz çalıştı.
Başarısız olduğunda aldığım mesaj:
Finished one cherry-pick.
# Not currently on any branch.
nothing to commit (working directory clean)
Could not apply 66c45e2... Needed subdir
Bu ilk squash taahhüdünden sonraki ilk seçim. Koşmak git status
temiz bir çalışma dizini verir. Daha sonra bir şey yaparsam git rebase --continue
, birkaç işlemden sonra çok benzer bir mesaj alırım. Daha sonra tekrar yaparsam, birkaç düzine işlemden sonra çok benzer bir mesaj alırım. Yine yaparsam, bu sefer yaklaşık yüz taahhütten geçer ve bu mesajı verir:
Automatic cherry-pick failed. After resolving the conflicts,
mark the corrected paths with 'git add <paths>', and
run 'git rebase --continue'
Could not apply f1de3bc... Incremental
Eğer koşarsam git status
, şunu elde ederim:
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: repo/file_A.cpp
# modified: repo/file_B.cpp
#
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: repo/file_X.cpp
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: repo/file_Z.imp
"Her ikisi de değiştirilmiş" bit bana garip geliyor, çünkü bu sadece bir seçimin sonucuydu. Ayrıca, "çatışmaya" bakarsam, bir sürümü [sekme] karakteriyle başlayan diğeri dört boşluklu tek bir satıra kaynar. Bu, yapılandırma dosyamı nasıl ayarladığımla ilgili bir sorun olabileceği gibi geldi, ancak içinde bir şey yok. (Core.ignorecase'in true olarak ayarlandığını fark ettim, ama açıkça git-clone bunu otomatik olarak yaptı. Orijinal kaynağın bir Windows makinesinde olduğu düşünüldüğünde tamamen şaşırmadım.)
File_X.cpp dosyasını el ile düzeltirsem, kısa bir süre sonra başka bir çakışma ile başarısız olur, bu kez bir sürümün var olduğunu düşündüğü ve bir sürümün olmaması gerektiğini düşündüğü bir dosya (CMakeLists.txt) arasında. Bu çatışmayı (yaptığım) istediğimi söyleyerek düzeltirsem, birkaç işlemin ardından şimdi önemsiz olmayan bazı değişiklikler olduğu başka bir çakışma (aynı dosyada) alırım. Hala çatışmaların yolunun sadece% 25'i.
Ayrıca, bu çok önemli olabileceğinden, bu projenin bir svn deposunda başladığını belirtmeliyim. Bu başlangıç tarihi büyük olasılıkla bu svn deposundan içe aktarılmıştır.
Güncelleme # 2:
Bir toygarda (Jefromi'nin yorumlarından etkilenerek), repo_squash.sh dosyamı şu şekilde değiştirmeye karar verdim:
rm -rf repo_squash
git clone repo repo_squash
cd repo_squash/
git rebase --strategy theirs -i bd6a09a484b8230d0810e6689cf08a24f26f287a
Ve sonra, orijinal girişleri olduğu gibi kabul ettim. Yani, "rebase" bir şeyi değiştirmemeliydi. Daha önce açıklanan aynı sonuçlarla sonuçlandı.
Güncelleme # 3:
Alternatif olarak, stratejiyi atlar ve son komutu yerine koyarsam:
git rebase -i bd6a09a484b8230d0810e6689cf08a24f26f287a
Artık "taahhüt edilecek hiçbir şey yok" sorununu çözmüyorum, ama yine de diğer çatışmalardan ayrıldım.
Sorunu yeniden oluşturan oyuncak deposuyla güncelleme:
test_squash.sh (bu gerçekten çalıştırdığınız dosyadır):
#========================================================
# Initialize directories
#========================================================
rm -rf test_squash/ test_squash_clone/
mkdir -p test_squash
mkdir -p test_squash_clone
#========================================================
#========================================================
# Create repository with history
#========================================================
cd test_squash/
git init
echo "README">README
git add README
git commit -m"Initial commit: can't easily access for rebasing"
echo "Line 1">test_file.txt
git add test_file.txt
git commit -m"Created single line file"
echo "Line 2">>test_file.txt
git add test_file.txt
git commit -m"Meant for it to be two lines"
git checkout -b dev
echo Meaningful code>new_file.txt
git add new_file.txt
git commit -m"Meaningful commit"
git checkout master
echo Conflicting meaningful code>new_file.txt
git add new_file.txt
git commit -m"Conflicting meaningful commit"
# This will conflict
git merge dev
# Fixes conflict
echo Merged meaningful code>new_file.txt
git add new_file.txt
git commit -m"Merged dev with master"
cd ..
#========================================================
# Save off a clone of the repository prior to squashing
#========================================================
git clone test_squash test_squash_clone
#========================================================
#========================================================
# Do the squash
#========================================================
cd test_squash
GIT_EDITOR=../test_squash_helper.sh git rebase -i HEAD@{7}
#========================================================
#========================================================
# Show the results
#========================================================
git log
git gc
git reflog
#========================================================
test_squash_helper.sh (test_sqash.sh tarafından kullanılır):
# If the file has the phrase "pick " in it, assume it's the log file
if grep -q "pick " $1
then
sed -e "s/pick \(.*\) \(Meant for it to be two lines\)/squash \1 \2/g" < $1 > $1.tmp
mv $1.tmp $1
# Else, assume it's the commit message file
else
# Use our pre-canned message
echo "Created two line file" > $1
fi
PS: Evet, emacs'ı geri dönüş düzenleyicisi olarak kullandığımı gördüğünüzde bazılarınızın kötü olduğunu biliyorum.
PPS: Rebase'den sonra mevcut depodaki tüm klonlarımızı patlatmamız gerektiğini biliyoruz. ("Yayımlandıktan sonra bir havuzu yeniden oluşturmayacaksınız" satırları boyunca.)
PPPS: Birisi bana buna nasıl ödül ekleyeceğini söyleyebilir mi? Düzenleme modunda veya görüntüleme modundayken bu ekranın hiçbir yerinde bu seçeneği görmüyorum.
rebase --interactive
- bunlar git denemesi için bir tür eylemler listesidir. Bunu, çatışmalara neden olan tek bir squash'e indirgemenizi ve yardımcı betiklerinizin tüm ekstra karmaşıklığından kaçınmayı umuyordum. Diğer eksik bilgiler, çatışmaların ortaya çıktığı zamandır - git yamaları kabak oluşturmak için uyguladığında mı, yoksa kabaktan geçip bir sonraki yamayı uyguladığında mı? (Ve GIT_EDITOR kludge'nizde kötü bir şey olmadığından emin misiniz? Basit test davası için başka bir oy.)
rebase -p
)