Wyślij żądanie ściągnięcia na GitHub tylko dla ostatniego zatwierdzenia


280

Rozwinąłem projekt na githubie i z powodzeniem wprowadzam zmiany w moim lokalnym mistrzu i staram się zacząć na githubie. Chcę wysłać żądanie ściągnięcia, ale chcę tylko dołączyć ostatnie zatwierdzenie. Interfejs żądania ściągania na github.com pokazuje 9 ostatnich zatwierdzeń i nie wiem, jak to przefiltrować.

Próbowałem zrozumieć, czy powinienem utworzyć nowy oddział lokalny, sprawdzić to i jakoś zresetować lub zmienić bazę na poprzednią? Następnie zastosować moje ostatnie zatwierdzenie od mojego wzorca przez id do nowej gałęzi lokalnej i użyć tego do żądania ściągnięcia?

Usiłuję uporządkować koncepcje i opracować odpowiednie wiersze poleceń, aby zrobić to, czego potrzebuję.


A co się stanie, jeśli wykonasz żądanie ściągnięcia ze wszystkimi innymi zatwierdzeniami? Myślałem, że git jest wystarczająco sprytny, aby zignorować (lub przekazać) zatwierdzenia, które już ściągnął?
jayarjo

3
Przypuszczalnie podmiot działający na rynku wyższym jeszcze nie zaakceptował lub nie chce interweniujących zobowiązań.
Michael Scott Cuthbert

@jayarjo Na przykład wprowadziłem inne zmiany, których nie chcę wysyłać w górę. Zmiany w git ignorują główne repozytorium nie będą na przykład potrzebne. Nic prostszego z git.
Martin

Powiązane: Kilka dobrych szczegółów na temat różnic w żądaniach ściągania w Git (oprogramowanie) i GitHub (usługa internetowa)
RBT

Odpowiedzi:


302

Musisz w zasadzie utworzyć nowy oddział i wybrać wybory, które chcesz do niego dodać.

Uwaga: możesz potrzebować ich przed poleceniami kasy / cherry-pick

git remote add upstream <git repository>

git remote update

git checkout -b <new-branch-name> upstream/master

git cherry-pick <SHA hash of commit>

git push origin <new-branch-name>

Następnie zobaczysz <new-branch-name>gałąź na github, przełączysz się na nią i możesz przesłać żądanie ściągnięcia z żądanymi zmianami.


32
Muszę również git remote add upstream <git repository>i git remote updateprzed uruchomieniem git checkout -b upstream upstream / master.
plainjimbo

6
To działa, ale nie tak należy to robić, ponieważ teraz twoja gałąź upstream i upstream / master są różne i zawsze będą różne, jeśli scalenie twojego żądania ściągania nie jest pierwszą rzeczą, którą robi. Z tego powodu powinieneś robić stackoverflow.com/a/5256304/1904815 .
JonnyJD,

2
Aby rozwinąć: To nie jest problem techniczny, ale logiczny. Jeśli chcesz zrobić coś z upstreamem (jak łączenie stamtąd), musisz dodać gałąź „real-upstream” lub zresetować upstream (nie pozostawiając lokalnego oddziału dla twojego żądania ściągania dla dodatkowych zmian).
JonnyJD,

15
Dlaczego, u licha, potrzebuję dodatkowej gałęzi, aby utworzyć PR dla jednej zmienionej linii kodu ?! Czy ktoś w github to przemyślał?
CodeManX

2
@JonHanna Nie ... dlaczego w ogóle musisz połączyć oddział? Dlaczego nie możesz po prostu scalić zatwierdzenia?
Kevin Krumwiede,

57

Utwórz nowy oddział, zaczynając od najnowszego zatwierdzenia, które również znajduje się w repozytorium źródłowym:

git branch new-branch origin/master
git checkout new-branch

Następnie użyj, git cherry-pickaby uzyskać pojedyncze zatwierdzenie, dla którego chcesz pobrać żądanie. Jeśli gałąź z tym zatwierdzeniem zostanie wywołana, featurea żądane zatwierdzenie jest ostatnim zatwierdzeniem w tej gałęzi, będzie to

git cherry-pick feature

Zakładając, że ta łatka obowiązuje bez konfliktu, masz teraz gałąź, dla której możesz wykonać polecenie ściągnięcia.

W drugim kroku musisz teraz zdecydować, co zrobić ze swoim featureoddziałem. Jeśli nie opublikowałeś jeszcze swoich zmian w tej gałęzi, najlepszą procedurą jest prawdopodobnie ponowne wydanie tej gałęzi na nową gałąź (i usunięcie ostatniego zatwierdzenia, jeśli nie zostanie to zrobione automatycznie git rebase).


Dostaję tę wiadomość po wiśniowym pobraniu. nic nie dodaje do zatwierdzenia, ale obecne są nieśledzone pliki (do śledzenia użyj „git add”). Wszystko jest w moim mistrzu, ale muszę zrobić gałąź z góry.
Kevin Hakanson,

5
Jeśli featurejest już popełnione origin/master, nic się nie dzieje podczas cherry-pick. Nowa gałąź powinna pochodzić upstream/master(tj. Odpowiedź Kevina Hakansona)
ohho,

26

Skończyło się na tym, że rozwidliłem widelec i chciałem złożyć prośbę o wycofanie do pierwotnego projektu.

Miałem:

  • orignal_project
  • forked_project (stworzony na podstawie oryginalnego projektu w SHA: 9685770)
  • my_fork (utworzony z rozwidlonego projektu w SHA: 207e29b)
  • zatwierdzenie w moim rozwidleniu (SHA: b67627b), które chciałem przesłać z powrotem do oryginalnego projektu

Aby to zrobić, ja:

  1. utworzył nowy oddział z SHA, w którym pierwotny projekt został rozwidlony
  2. wyciągnął wszystko z oryginalnego projektu
  3. Cherry wybrała zatwierdzenie, które chciałem przesłać jako żądanie ściągnięcia
  4. pchnęło to wszystko do github

Polecenia git wyglądały mniej więcej tak:

  1. git branch my-feature-request 9685770
  2. git sprawdź moje żądanie funkcji
  3. git pull https://github.com/original_project/original_project.git
  4. git cherry-pick b67627b
  5. git push origin my-feature-request

Następnie wybrałem moją prośbę o funkcję jako gałąź dla mojego żądania ściągnięcia do oryginalnego projektu.


6

To prawie działało dla mnie:

git checkout -b upstream upstream/master

git cherry-pick <SHA hash of commit>

git push origin upstream

Jedyną różnicą było to:

git push origin upstream:upstream

Musiałem zmienić tę ostatnią linię, aby git push utworzył gałąź upstream w moim repozytorium GitHub, tak żebym mógł z tego zrobić PR.


5

Dokonałem już zatwierdzenia, które chciałem móc izolować jako żądanie ściągnięcia z powrotem do bieżącej gałęzi.

Sprawdziłem więc nowy oddział

git checkout -b isolated-pull

I tutaj moje rozwiązanie różni się od @Kevin Hakanson , ponieważ muszę zresetować tę gałąź do miejsca w historii, od którego chcę się różnić

git reset --hard [sha-to-diff-by]

I wybierz cherry zatwierdzenie, z którego chcę utworzyć izolowane żądanie ściągnięcia

git cherry-pick [my-isolated-commit-sha]

Wreszcie popchnij go do pilota

git push origin isolated-pull

I ściągnij żądanie danych shi.


1

Rozwiązanie polegające na utworzeniu nowego (tymczasowego) oddziału, wybranie go i utworzenie żądania ściągania dla tego oddziału nie spełniło moich oczekiwań. Nie chciałem zmieniać mojego repozytorium, aby udostępnić zestaw zatwierdzeń, więc wpadłem na następującą alternatywę:

Najpierw utwórz pliki łatek dla wszystkich interesujących cię zmian:

git format-patch -1 <sha>

Jeśli okazuje się, że zatwierdzenie zainteresowania jest ostatnim, którego możesz użyć HEADzamiast tego <sha>.

Teraz możesz wysłać poprawki do opiekuna repozytorium źródłowego, który może je zastosować:

git branch new-branch <master or some older commit where the fork diverged>
git checkout new-branch

git am < <the patch>
...

git checkout master
git merge new-branch

Wreszcie powinno to wyglądać tak samo, jakby gałąź tymczasowa została scalona przez żądanie ściągnięcia, ale bez posiadania tej dodatkowej gałęzi w repozytorium wideł.


0

Na podstawie odpowiedzi @ kevin-hakanson napisałem ten mały skrypt bash, aby ułatwić ten proces. Dodanie repozytorium nadrzędnego, jeśli jeszcze nie istnieje (monit o adres URL), a następnie monit o podanie nazwy nowej gałęzi do utworzenia i tag / SHA zatwierdzenia do pobrania wiśniowego w tej gałęzi. Sprawdza, w której gałęzi lub zatwierdzeniu jesteś aktualnie, a następnie przechowuje wszelkie zmiany, abyś mógł pobrać nową gałąź. Strategia scalania zachowuje zmiany w stosunku do zatwierdzonego wyboru. Po wypchnięciu nowej gałęzi do origin(zakłada się, że jest to nazwa twojego zdalnego repo), gałąź lub zatwierdzenie, w którym byłeś wcześniej, jest ponownie sprawdzane, a twoje poprzednie zmiany wyskoczyły z ukrycia.

if ! git remote | grep -q upstream; then
    read -p "Upstream git repo URL: " upstream
    git remote add upstream $upstream
    git remote update
fi

read -p "Feature branch name: " feature_branch
# note: giving "master" is the same as giving the SHA it points to
read -p "SHA of commit to put on branch: " sha

current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" == "HEAD" ]; then
    # detached HEAD; just get the commit SHA
    current_branch=$(git rev-parse --short HEAD)
fi
git stash
git checkout -b $feature_branch upstream/master
git cherry-pick --strategy=recursive -X theirs $sha
git push origin $feature_branch
git checkout $current_branch
git stash pop

(To zadziałało dla mnie w kilku prostych testach, ale nie jestem programistą bash ani ekspertem od gitów, więc daj mi znać, jeśli są przypadki, które przegapiłem, które można lepiej zautomatyzować!)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.