Jak wybrać zakres commitów i połączyć się z inną gałęzią?
Mam następujący układ repozytorium:
- master branch (produkcja)
- integracja
- Praca
To, co chcę osiągnąć, to wybrać zakres commitów z działającej gałęzi i połączyć je z gałęzią integracyjną. Jestem całkiem nowy w git i nie mogę dowiedzieć się, jak dokładnie to zrobić (cherry zbieranie zakresów commit w jednej operacji, a nie Łączenie) bez brudzenia repozytorium. Jakieś wskazówki lub przemyślenia na ten temat? Dzięki!
7 answers
Jeśli chodzi o zakres commitów, cherry-picking jest nie było praktyczne.
Jak wspomniano poniżej przez Keitha Kim, Git 1.7.2 + wprowadził możliwość cherry-pick zakresu commitów (ale nadal musisz być świadomy konsekwencji cherry-pickingu dla przyszłej merge )
Git cherry-pick " nauczył się wybierać zakres commitów
(np. "cherry-pick A..B
"i"cherry-pick --stdin
"), podobnie "git revert
"; nie obsługują one jednak ładniejsze sterowanie sekwencyjne "rebase [-i]
" ma.
Damian komentarze i ostrzega:
W formularzu"
cherry-pick A..B
",A
powinny być starsze niżB
.
jeśli są w złej kolejności, polecenie po cichu zawiedzie .
Jeśli chcesz wybrać zakres B
przez D
(włącznie) , to B^..D
.
Patrz " Git create branch from range of previous commits?" jako ilustracja.
Jak Jubobs wspomina w komentarzach :
Zakłada to, że
B
nie jest commitem root; w przeciwnym razie pojawi się błąd"unknown revision
".
Uwaga: od wersji Git 2.9.x / 2.10 (Q3 2016), możesz wybrać zakres commitów bezpośrednio na orphan branch( pusta Głowica): zobacz " jak zmienić istniejącą gałąź w git ".
Oryginalna odpowiedź (styczeń 2010)
A rebase --onto
byłoby lepiej, gdzie ty powtórz podany zakres commit na górze swojej gałęzi integracji, jak to opisał Charles Bailey tutaj .
aby zobaczyć praktyczny przykład git rebase --onto
, poszukaj "oto jak przeszczepić gałąź tematyczną opartą na jednej gałęzi do drugiej" na stronie podręcznika git rebase, aby zobaczyć praktyczny przykład git rebase --onto
)
Jeśli Twoja bieżąca gałąź jest integracją:
# 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
To odtworzy wszystko pomiędzy:
- po rodzicu
first_SHA-1_of_working_branch_range
(stąd~1
): pierwszy commit you chcesz odtworzyć - do "
integration
"(co wskazuje na ostatni commit, który chcesz odtworzyć, z gałęziworking
)
Do "tmp
"(co wskazuje na to, gdzie integration
wskazywało wcześniej)
Jeśli wystąpi jakikolwiek konflikt, gdy jeden z tych commitów zostanie powtórzony:
- albo Rozwiąż i uruchom "
git rebase --continue
". - lub pomiń tę łatkę, a zamiast tego Uruchom "
git rebase --skip
" - lub anulować wszystko za pomocą "
git rebase --abort
"(i umieścić z powrotem gałąźintegration
natmp
oddział)
Po tym rebase --onto
, integration
zostanie zwrócony przy ostatnim commicie gałęzi integracyjnej (czyli gałęzi" tmp
" + wszystkie powtórzone commity)
Z cherry-picking lub rebase --onto
, nie zapominaj, że ma to konsekwencje dla kolejnych połączeń, jak opisano tutaj .
Czystym rozwiązaniem "cherry-pick
" jest omawiane tutaj i obejmowałoby coś w rodzaju:
Jeśli chcesz użyć patcha to " Git format-patch|Git am" a "git cherry" to twoje opcje.
Obecniegit cherry-pick
akceptuje tylko jeden commit, ale jeśli chcesz wybrać zakresB
przezD
, to będzie toB^..D
w git lingo, więc
git rev-list --reverse --topo-order B^..D | while read rev
do
git cherry-pick $rev || break
done
Ale w każdym razie, kiedy musisz "odtworzyć" zakres commitów, słowo "replay" powinno skłonić cię do użycia funkcji" rebase
" W Git.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 06:44:24
Od wersji git v1.7. 2 cherry pick może akceptować zakres commitów:
git cherry-pick
nauczył się wybierać zakres commitów (np.cherry-pick A..B
icherry-pick --stdin
), podobnie jakgit revert
; te nie wspierają jednak ładniejszej kontroli sekwencjonowaniarebase [-i]
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 22:22:29
Jesteś pewien, że nie chcesz połączyć gałęzi? Jeśli działająca gałąź ma kilka ostatnich zmian, których nie chcesz, możesz po prostu utworzyć nową gałąź z nagłówkiem w miejscu, w którym chcesz.
Teraz, jeśli naprawdę chcesz wybrać zakres commitów, z jakiegokolwiek powodu, eleganckim sposobem na to jest po prostu wyciągnięcie patchsetu i zastosowanie go do nowej gałęzi integracji: {]}
git format-patch A..B
git checkout integration
git am *.patch
To jest zasadniczo to, co i tak robi git-rebase, ale bez potrzeby grania w gry. Możesz dodać --3way
do git-am
, jeśli chcesz się połączyć. Upewnij się, że nie ma innych*.łataj pliki już w katalogu, w którym to robisz, jeśli postępujesz zgodnie z instrukcjami dosłownie...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-04 09:32:52
Załóżmy, że masz 2 gałęzie,
"branchA": zawiera commity, które chcesz skopiować (z "commitA" do "commitB"
"branchB": gałąź, z której chcesz przenieść commity z "branchA"
1)
git checkout <branchA>
2) get the IDs of "commitA" and "commit"
3)
git checkout <branchB>
4)
git cherry-pick <commitA>^..<commitB>
5) Jeśli masz konflikt, rozwiąż go i wpisz
git cherry-pick --continue
Aby kontynuować proces wyboru wiśni.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 14:29:48
Zawinąłem Kod VonC do krótkiego skryptu bash, git-multi-cherry-pick
, dla łatwego działania:
#!/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
Obecnie używam tego, gdy odbudowuję historię projektu, który miał zarówno kod 3rd-party, jak i modyfikacje mieszane razem w tym samym bagażniku svn. Teraz dzielę core 3rd party code, 3rd party modules i customizations na ich własne gałęzie git dla lepszego zrozumienia dostosowań w przyszłości. git-cherry-pick
jest pomocny w tej sytuacji, ponieważ mam dwa drzewa w tym samym repozytorium, ale bez wspólnego przodka.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:32
Wszystkie powyższe opcje monitują o rozwiązanie konfliktów scalania. Jeśli łączysz zmiany wprowadzone dla zespołu, trudno jest rozwiązać konflikty scalania ze strony programistów i kontynuować. Jednak "Git merge" zrobi scalenie w jednym ujęciu, ale nie możesz przekazać zakresu poprawek jako argumentu. musimy użyć poleceń "git diff" i "GIT apply"aby wykonać zakres scalania obrotów. Zauważyłem, że "git apply" nie powiedzie się, jeśli plik patch ma diff dla zbyt wielu plików, więc musimy Utwórz łatkę na plik, a następnie zastosuj. Zauważ, że skrypt nie będzie w stanie usunąć plików usuniętych w gałęzi source. Jest to rzadki przypadek, można ręcznie usunąć takie pliki z gałęzi docelowej. Status zakończenia "git apply" nie jest zerowy, jeśli nie jest w stanie zastosować poprawki, jednak jeśli użyjesz opcji-3way, powróci ona do 3 way merge i nie musisz się martwić o tę awarię.
Poniżej znajduje się skrypt.
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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 09:08:39
Inną opcją może być scalenie z naszą strategią do commita przed zakresem, a następnie' normalne ' scalenie z ostatnim commitem tego zakresu (lub gałęzią, gdy jest ostatnim). Przypuśćmy więc, że tylko 2345 i 3456 commity master zostaną scalone w gałąź funkcji:
master: 1234 2345 3456 4567
W gałęzi funkcji:
git merge -s ours 4567 git merge 2345
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-16 12:47:03