Am urmatoarele depozit layout:
Ceea ce vreau să realizeze este să aleagă o serie de comite de lucru ramură și merge în integrarea ramură. Sunt destul de nou la git si nu pot't dau seama cum de a face exact acest lucru (cherry picking a comite variază într-o singură operație nu fuzionează) fără încurcați depozit sus. Ceva sfaturi sau idei despre asta? Multumesc!!!
Când e vorba de o serie de comite, cherry-picking este a fost nu practice.
Ca menționate mai jos de către Keith Kim, Git 1.7.2+ a introdus posibilitatea de a alege o gamă de comite (dar încă mai trebuie să fie conștienți de consecință a cherry-picking pentru viitor fuziona)
git cherry-pick" a învățat să alegeți o gamă de comite (de exemplu, "
cherry-pick O..B
" și "cherry-pick-stdin
"), astfel încât a făcut "git reveni
"; acestea nu susțin mai frumos secventiere de control "rebazare [-i]
" are, totuși.
damian comentarii și ne avertizează:
În "
cherry-pick O..B
" forma, " A "ar trebui să fie mai în vârstă decât "B". Dacă ar're greșit pentru comanda va eșua în tăcere.
Dacă doriți pentru a alege gama " B " la " D " (inclusiv) ar fi B^..D
.
A se vedea "Git de a crea filiala din intervalul precedent comite?" ca o ilustrare.
Ca Jubobs mentiuni în comentarii:
Aceasta presupune că " B " nu este o rădăcină a comis; te'll obține un "
necunoscut revizuire
" eroare în caz contrar.
Notă: ca de Git 2.9.x/2.10 (T3 2016), puteți alege o gamă de comite direct pe un orfan de ramură (capul gol): a se vedea "Cum să facă existente ramură orfan in git".
Original răspuns (ianuarie 2010)
O rebazare --pear fi mai bine, în cazul în care vă reda anumit interval de comite pe partea de sus a integrării ramură, ca [Charles Bailey descrise aici][10]. (de asemenea, uita-te pentru "Aici este modul în care ar transplant un subiect ramură bazată pe o ramură la alta" în [git rebazare om page][11], pentru a vedea un exemplu practic de
git rebazare --pe`)
Dacă dumneavoastră curentă branch este o integrare:
# Checkout a new temporary branch at the current location
git checkout -b tmp
# Move the integration branch to the head of the new patchset
git branch -f integration last_SHA-1_of_working_branch_range
# Rebase the patchset onto tmp, the old location of integration
git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration
Care va reda totul între:
first_SHA-1_of_working_branch_range
(prin urmare ~1
): primul comite doriți pentru a redapentru a "tmp
" (care indică în cazul în care "integrarea" a fost îndreptată înainte)
Dacă există vreun conflict atunci când unul dintre cei comite este redat:
git rebazare-continua
". git rebazare --skip
"git rebazare --abandonați
" (și a pus înapoi "integrarea" ramura pe tmp
branch)După asta rebazare --pe, "integrarea" va fi înapoi la ultimul comite de integrare ramură (care este "
tmp`" sucursală + toate redate comite)
Cu cherry-picking sau rebazare --pe`, nu uita că are consecințe ulterioare fuzionează, ca descrise aici.
Pur "cherry-pick
" soluția este a discutat aici, și ar implica ceva de genul:
Dacă doriți să utilizați un plasture abordare apoi "git format-patch-uri|git sunt" și "git cherry" sunt opțiunile. În prezent,
git cherry-pick
acceptă doar un singur comis-o, dar dacă vrei să alegi gama " B " la "D", care ar fiB^..D
in git lingo, deci
git rev-list --reverse --topo-order B^..D | while read rev
do
git cherry-pick $rev || break
done
Dar, oricum, atunci când aveți nevoie pentru a "reluarea" de o serie de comite, cuvântul "reluarea" ar trebui să te împingă să utilizați "rebazare
" caracteristică de Git.
Ca de git v1.7.2 alege cireșe poate accepta o gamă largă de comite:
git cherry-pick
a învățat să alegeți o gamă de comite (de exemplu, alege O..B " și " cherry-pick-stdin), deci v
git reveni; acestea nu susțin mai frumos secventiere de control
rebazare [-i]` are, totuși.
Să presupunem că aveți 2 ramuri,
"branchA" : include comite doriți să-l copiați (de la "commitA" pentru "commitB"
"branchB" : ramura vrei angajează să fie transferate de la "branchA"
git checkout <branchA>
a lua id-Urile de "commitA" și "commitB"
git checkout <branchB>
git cherry-pick <commitA>^..<commitB>
git cherry-pick --continue
pentru a continua cherry-pick proces.
Ești sigur că don't vreau să fuzioneze ramuri? Dacă în ramură a unor recente se angajează să don't doriți, puteți crea o nouă ramură cu un CAP în punctul în care doriți.
Acum, dacă tu chiar vrei să alegi o gama de comite, indiferent de motiv, un mod elegant de a face acest lucru este de a trage de o patchset și se aplică la noi de integrare ramură:
git format-patch A..B
git checkout integration
git am *.patch
Aceasta este, în esență ceea ce git-rebazare este de a face oricum, dar fără a fi nevoie pentru a juca jocuri. Puteți adăuga `--3way " la " git-mă dacă aveți nevoie pentru a merge. Asigurați-vă că nu există alte *.fișierele de corecții deja în directorul în care ați face acest lucru, dacă urmați instrucțiunile cuvânt cu cuvânt...
Am înfășurat VonC's code într-un scurt script bash, git-multi-cherry-pick
, pentru ușor de funcționare:
#!/bin/bash
if [ -z $1 ]; then
echo "Equivalent to running git-cherry-pick on each of the commits in the range specified.";
echo "";
echo "Usage: $0 start^..end";
echo "";
exit 1;
fi
git rev-list --reverse --topo-order $1 | while read rev
do
git cherry-pick $rev || break
done
Am'm în prezent, folosind acest lucru ca am reconstrui istoria de un proiect care a avut ambele 3rd-petrecere cod și particularizări amestecate împreună în același svn portbagaj. Am'm acum despart de bază 3rd petrecere cod, module 3rd party, și particularizări pe propria lor git ramuri pentru o mai bună înțelegere a particularizări merge înainte. `git-cherry-pick este de ajutor în această situație, deoarece am doi copaci în aceeași magazie, dar fără un strămoș comun.
Toate opțiunile de mai sus vă va solicita pentru a rezolva fuziona conflicte. Dacă sunteți fuzionarea modificările angajat pentru o echipa, este dificil de a obține rezolvat merge conflictele de la dezvoltatori și continua. Cu toate acestea, "git merge" va fuziona într-o singură lovitură, dar nu se poate trece un interval de revizii ca argument. trebuie să utilizați "git diff" și "git se aplică" comenzi pentru a face fuziunea gama de turatii. Am observat că "git se aplică" va eșua în cazul în care patch-uri de fișiere are dif de prea multe fișiere, așa că avem pentru a crea un patch pe fișier și apoi se aplică. Rețineți că script-ul nu va fi capabil de a șterge fișierele care sunt șterse în sursa de ramură. Acesta este un caz rar, aveți posibilitatea să ștergeți manual fișierele astfel de țintă ramură. Starea de iesire de "git se aplică" nu este zero dacă nu este în măsură să aplice patch-uri, cu toate acestea, dacă utilizați -3way opțiune va cădea înapoi la 3 mod de îmbinare și don't trebuie să vă faceți griji despre acest eșec.
Mai jos este script-ul.
enter code here
#!/bin/bash
# This script will merge the diff between two git revisions to checked out branch
# Make sure to cd to git source area and checkout the target branch
# Make sure that checked out branch is clean run "git reset --hard HEAD"
START=$1
END=$2
echo Start version: $START
echo End version: $END
mkdir -p ~/temp
echo > /tmp/status
#get files
git --no-pager diff --name-only ${START}..${END} > ~/temp/files
echo > ~/temp/error.log
# merge every file
for file in `cat ~/temp/files`
do
git --no-pager diff --binary ${START}..${END} $file > ~/temp/git-diff
if [ $? -ne 0 ]
then
# Diff usually fail if the file got deleted
echo Skipping the merge: git diff command failed for $file >> ~/temp/error.log
echo Skipping the merge: git diff command failed for $file
echo "STATUS: FAILED $file" >> /tmp/status
echo "STATUS: FAILED $file"
# skip the merge for this file and continue the merge for others
rm -f ~/temp/git-diff
continue
fi
git apply --ignore-space-change --ignore-whitespace --3way --allow-binary-replacement ~/temp/git-diff
if [ $? -ne 0 ]
then
# apply failed, but it will fall back to 3-way merge, you can ignore this failure
echo "git apply command filed for $file"
fi
echo
STATUS=`git status -s $file`
if [ ! "$STATUS" ]
then
# status is null if the merged diffs are already present in the target file
echo "STATUS:NOT_MERGED $file"
echo "STATUS: NOT_MERGED $file$" >> /tmp/status
else
# 3 way merge is successful
echo STATUS: $STATUS
echo "STATUS: $STATUS" >> /tmp/status
fi
done
echo GIT merge failed for below listed files
cat ~/temp/error.log
echo "Git merge status per file is available in /tmp/status"
O altă opțiune ar putea fi pentru a fuziona cu strategia noastră de a comite înainte de gamă și apoi o 'normal' fuziona cu ultimul comite acel interval (sau ramură atunci când este ultima). Deci, să presupunem că doar 2345 și 3456 comite de master să fie comasate în funcție de ramură:
maestrul: O mie două sute treizeci și patru Două mii trei sute patruzeci și cinci Trei mii patru sute cincizeci și șase Patru mii cinci sute șaizeci și șapte deîn funcție de ramura:
git merge-s-a noastră 4567 git merge 2345