Senden Sie eine Pull-Anfrage auf GitHub, um nur das letzte Commit zu erhalten

280

Ich habe ein Projekt auf Github gegabelt und nehme erfolgreich Änderungen an meinem lokalen Master vor und dränge auf Github zum Ursprung. Ich möchte eine Pull-Anfrage senden, aber nur das letzte Commit einschließen. Die Pull-Request-Benutzeroberfläche auf github.com zeigt die letzten 9 Commits an, und ich weiß nicht, wie ich das herausfiltern soll.

Ich habe versucht zu verstehen, ob ich einen neuen lokalen Zweig erstellen, das überprüfen und irgendwie zurücksetzen oder auf Upstream zurücksetzen soll. Wenden Sie dann mein letztes Commit von meinem Master per ID auf den neuen lokalen Zweig an und verwenden Sie dieses für die Pull-Anforderung?

Ich versuche, die Konzepte richtig zu machen und die richtigen Befehlszeilen zu finden, um das zu tun, was ich brauche.

Kevin Hakanson
quelle
Und was passiert, wenn Sie mit allen anderen Commits eine Pull-Anfrage stellen? Ich dachte, Git ist klug genug, um die Commits zu ignorieren (oder zu bestehen), die es bereits eingezogen hat?
Jayarjo
3
Vermutlich hat der Upstream die dazwischenliegenden Commits noch nicht akzeptiert oder will sie nicht.
Michael Scott Cuthbert
@jayarjo Ich habe zum Beispiel andere Änderungen vorgenommen, die ich nicht stromaufwärts senden möchte. Änderungen an git ignorieren beispielsweise das Haupt-Repository nicht. Mit git ist das nicht einfach.
Martin
Verwandte: Einige gute Details darüber, wie sich die Pull-Anforderungen in Git (der Software) und GitHub (dem Webdienst) unterscheiden
RBT

Antworten:

302

Sie müssen im Grunde genommen einen neuen Zweig erstellen und die Commits auswählen, die Sie hinzufügen möchten.

Hinweis: Möglicherweise benötigen Sie diese vor den Befehlen checkout / 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>

Anschließend sehen Sie einen <new-branch-name>Zweig auf Github, wechseln zu diesem und können die Pull-Anfrage mit den gewünschten Änderungen senden.

Kevin Hakanson
quelle
32
Ich muss auch git remote add upstream <git repository>und git remote updatebevor ich git checkout -b upstream upstream / master ausführen kann.
Plainjimbo
6
Dies funktioniert, ist aber nicht so, wie Sie es tun sollen, da jetzt Ihr Upstream-Zweig und Ihr Upstream / Master unterschiedlich sind und immer unterschiedlich sein werden, wenn das Zusammenführen Ihrer Pull-Anforderung nicht das erste ist, was Upstream tut. Aus diesem Grund sollten Sie stackoverflow.com/a/5256304/1904815 bevorzugen .
JonnyJD
2
Um es näher zu erläutern: Dies ist kein technisches Problem, sondern ein logisches. Wenn Sie etwas mit Upstream tun möchten (z. B. von dort aus zusammenführen), müssen Sie einen Zweig "Real-Upstream" hinzufügen oder Ihren Upstream zurücksetzen (wobei für Ihre Pull-Anforderung für zusätzliche Änderungen kein lokaler Zweig übrig bleibt).
JonnyJD
15
Warum um alles in der Welt brauche ich einen zusätzlichen Zweig, nur um eine PR für eine einzelne geänderte Codezeile zu erstellen?! Hat jemand bei Github das durchdacht?
CodeManX
2
@ JonHanna Nein ... warum musst du überhaupt einen Zweig zusammenführen? Warum können Sie ein Commit nicht einfach zusammenführen?
Kevin Krumwiede
57

Erstellen Sie einen neuen Zweig ab dem letzten Commit, der sich ebenfalls im Ursprungs-Repository befindet:

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

Verwenden Sie dann git cherry-pick, um das einzelne Commit abzurufen, für das Sie die Pull-Anforderung wünschen. Wenn der Zweig mit diesem Commit aufgerufen wird featureund das gewünschte Commit das letzte Commit in diesem Zweig ist, ist dies der Fall

git cherry-pick feature

Vorausgesetzt, dieser Patch gilt ohne Konflikte, haben Sie jetzt einen Zweig, für den Sie Ihre Pull-Anfrage ausführen können.

In einem zweiten Schritt müssen Sie nun entscheiden, was mit Ihrer featureNiederlassung geschehen soll. Wenn Sie Ihre Änderungen noch nicht in diesem Zweig veröffentlicht haben, ist es wahrscheinlich das beste Verfahren, diesen Zweig bei einem neuen Zweig neu zu gründen (und das letzte Commit zu entfernen, wenn dies nicht automatisch von erfolgt git rebase).

Lars Noschinski
quelle
Ich bekomme diese Nachricht nach dem Kirschpflücken. Es wurde nichts zum Festschreiben hinzugefügt, aber nicht verfolgte Dateien sind vorhanden (verwenden Sie "git add" zum Verfolgen). Alles ist in meinem Meister, aber ich muss meinen Zweig von stromaufwärts machen.
Kevin Hakanson
5
Wenn das featurebereits festgeschrieben ist origin/master, passiert während nichts cherry-pick. Der neue Zweig sollte von upstream/master(dh Kevin Hakansons Antwort) sein
ohho
26

Ich kam in eine Situation, in der ich eine Gabel gegabelt hatte und eine Pull-Anfrage an das ursprüngliche Projekt zurücksenden wollte.

Ich hatte:

  • orignal_project
  • forked_project (erstellt aus dem ursprünglichen Projekt bei SHA: 9685770)
  • my_fork (erstellt aus einem gegabelten Projekt bei SHA: 207e29b)
  • Ein Commit in meiner Gabel (SHA: b67627b), das ich an das ursprüngliche Projekt zurücksenden wollte

Um dies zu tun, ich:

  1. hat einen neuen Zweig von der SHA erstellt, in dem das ursprüngliche Projekt gegabelt wurde
  2. zog alles aus dem ursprünglichen Projekt
  3. Cherry wählte das Commit aus, das ich als Pull-Anfrage einreichen wollte
  4. schob alles auf Github

Die Git-Befehle waren ungefähr so:

  1. Git Branch My-Feature-Anfrage 9685770
  2. Git Checkout My-Feature-Anfrage
  3. git pull https://github.com/original_project/original_project.git
  4. Git Cherry-Pick b67627b
  5. Git Push Origin My-Feature-Anfrage

Dann habe ich meine Feature-Anfrage als Zweig für meine Pull-Anfrage zum ursprünglichen Projekt ausgewählt.

John Naegle
quelle
6

Das hat bei mir fast geklappt:

git checkout -b upstream upstream/master

git cherry-pick <SHA hash of commit>

git push origin upstream

Der einzige Unterschied war folgender:

git push origin upstream:upstream

Ich musste diese letzte Zeile ändern, damit Git Push den Upstream-Zweig in meinem GitHub-Repo erstellt, damit ich daraus PR machen konnte.

hi_tech_lowlife
quelle
5

Ich hatte bereits das Commit gemacht, das ich als Pull-Anfrage zurück in den aktuellen Zweig isolieren wollte.

Also habe ich eine neue Filiale ausgecheckt

git checkout -b isolated-pull

Und hier unterscheidet sich meine Lösung von der von @ Kevin Kevin Hakanson , da ich diesen Zweig an die Stelle in der Geschichte zurücksetzen muss, von der ich mich unterscheiden möchte

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

Wählen Sie das Commit aus, aus dem ich eine isolierte Pull-Anforderung erstellen möchte

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

Schieben Sie es schließlich auf die Fernbedienung

git push origin isolated-pull

Und ziehen Sie Anfrage dat shi.

irbanana
quelle
1

Die Lösung zum Erstellen eines neuen (temporären) Zweigs, zum Kirschpflücken und zum Erstellen der Pull-Anforderung für diesen Zweig hat mich nicht zufriedengestellt. Ich wollte mein Repository nicht ändern, um eine Reihe von Commits verfügbar zu machen, daher habe ich mir die folgende Alternative ausgedacht:

Erstellen Sie zuerst Patch-Dateien für alle Commits von Interesse:

git format-patch -1 <sha>

Wenn das Commit of Interest zufällig das letzte ist, können Sie es HEADstattdessen verwenden <sha>.

Jetzt können Sie die Patches an den Betreuer des Quell-Repositorys senden, der sie anwenden kann:

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

Schließlich sollte dies so aussehen, als ob ein temporärer Zweig durch eine Pull-Anforderung zusammengeführt wurde, ohne jedoch diesen zusätzlichen Zweig im Fork-Repository zu haben.

Johannes Jendersie
quelle
0

Basierend auf der Antwort von @ kevin-hakanson habe ich dieses kleine Bash-Skript geschrieben, um diesen Prozess zu vereinfachen. Es fügt das Upstream-Repo hinzu, falls es noch nicht vorhanden ist (und fordert Sie zur Eingabe der URL auf), und fordert Sie dann auf, sowohl den Namen des neu zu erstellenden Zweigs als auch das Tag / die SHA des Commits für Cherry Pick auf diesem Zweig anzugeben. Es überprüft, in welchem ​​Zweig oder Commit Sie sich gerade befinden, und speichert dann alle Änderungen, damit Sie den neuen Zweig auschecken können. Die Zusammenführungsstrategie behält die Änderungen aus dem von Kirschen ausgewählten Commit bei. Nachdem Sie den neuen Zweig auf origin(vermutlich der Name Ihres Remote-Repos) verschoben haben, wird der Zweig oder das Commit, auf dem Sie zuvor waren, erneut ausgecheckt und Ihre vorherigen Änderungen wurden aus dem Stash entfernt.

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

(Dies hat bei mir in ein paar einfachen Tests funktioniert, aber ich bin kein Bash-Programmierer oder Git-Experte. Lassen Sie mich wissen, wenn ich Fälle verpasst habe, die besser automatisiert werden könnten!)

Nathan
quelle