Envoyer une demande d'extraction sur GitHub pour la dernière validation uniquement

280

J'ai bifurqué un projet sur github et j'ai réussi à apporter des modifications à mon maître local et à pousser à l'origine sur github. Je souhaite envoyer une demande d'extraction, mais je souhaite uniquement inclure le dernier commit. L'interface utilisateur de demande de pull sur github.com affiche les 9 derniers commits et je ne sais pas comment filtrer cela.

J'essayais de comprendre si je devais créer une nouvelle branche locale, vérifier cela et en quelque sorte réinitialiser ou rebaser en amont? Appliquer ensuite mon dernier commit de mon maître par id à la nouvelle branche locale et l'utiliser pour la pull request?

J'essaie de bien comprendre les concepts et de trouver les bonnes lignes de commande pour faire ce dont j'ai besoin.

Kevin Hakanson
la source
Et que se passe-t-il si vous effectuez une pull request avec tous les autres commits? Je pensais que Git est assez intelligent pour ignorer (ou passer) les commits qu'il a déjà récupérés?
jayarjo
3
Vraisemblablement, l'amont n'a pas encore accepté ou ne veut pas que les intervenants s'engagent.
Michael Scott Cuthbert
@jayarjo J'ai par exemple apporté d'autres modifications que je ne souhaite pas envoyer en amont. Les modifications apportées à git ignorent le référentiel principal n'auront pas besoin par exemple. Rien de simple avec git.
Martin
Connexe: Quelques bons détails sur la façon dont les demandes de tirage sont différentes dans Git (le logiciel) et GitHub (le service Web)
RBT

Réponses:

302

Vous devez essentiellement créer une nouvelle branche et sélectionner les commits que vous souhaitez y ajouter.

Remarque: vous pourriez en avoir besoin avant les commandes 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>

Ensuite, vous verrez la <new-branch-name>branche sur github, basculez vers elle et pouvez soumettre la demande de pull avec les modifications que vous souhaitez.

Kevin Hakanson
la source
32
J'ai également besoin git remote add upstream <git repository>et git remote updateavant d'exécuter git checkout -b en amont en amont / maître.
plainjimbo
6
Cela fonctionne, mais ce n'est pas comme cela que vous êtes censé le faire, car maintenant votre branche en amont et en amont / maître sont différents et seront toujours différents si la fusion de votre demande d'extraction n'est pas la première chose en amont. Pour cette raison, vous devriez préférer faire stackoverflow.com/a/5256304/1904815 .
JonnyJD
2
Pour élaborer: Ce n'est pas un problème technique, mais logique. Lorsque vous voulez faire quoi que ce soit avec l'amont (comme la fusion à partir de là), vous devez ajouter une branche "réel en amont" ou réinitialiser votre amont (ne laissant aucune branche locale pour votre demande d'extraction pour des modifications supplémentaires).
JonnyJD
15
Pourquoi diable ai-je besoin d'une branche supplémentaire, uniquement pour créer un PR pour une seule ligne de code modifiée?! Est-ce que quelqu'un chez github y a réfléchi?
CodeManX
2
@JonHanna Non ... pourquoi devez-vous fusionner une branche? Pourquoi ne pouvez-vous pas simplement fusionner un commit?
Kevin Krumwiede
57

Créez une nouvelle branche à partir de la dernière validation, qui se trouve également dans le référentiel d'origine:

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

Ensuite, utilisez git cherry-pickpour obtenir le commit unique pour lequel vous souhaitez la demande de pull. Si la branche avec ce commit est appelée featureet que le commit que vous voulez est le dernier commit de cette branche, ce sera

git cherry-pick feature

En supposant que ce patch s'applique sans conflit, vous avez maintenant une branche pour laquelle vous pouvez faire votre demande de tirage.

Dans un deuxième temps, vous devez maintenant décider quoi faire de votre featureagence. Si vous n'avez pas encore publié vos modifications sur cette branche, la meilleure procédure consiste probablement à rebaser cette branche sur new-branch (et à supprimer le dernier commit, si cela n'est pas fait automatiquement par git rebase).

Lars Noschinski
la source
Je reçois ce message après la sélection. rien ajouté pour valider mais présence de fichiers non suivis (utilisez "git add" pour suivre). Tout est dans mon maître, mais je dois faire ma branche depuis l'amont.
Kevin Hakanson
5
Si le featureest déjà engagé origin/master, rien ne se passe pendant cherry-pick. La nouvelle succursale devrait provenir de upstream/master(c.-à-d., La réponse de Kevin Hakanson)
ohho
26

Je me suis retrouvé dans une situation où j'avais bifurqué une fourchette et que je voulais soumettre une demande de retrait au projet d'origine.

J'ai eu:

  • orignal_project
  • forked_project (créé à partir du projet original chez SHA: 9685770)
  • my_fork (créé à partir d'un projet forké chez SHA: 207e29b)
  • un commit dans ma fourchette (SHA: b67627b) que je voulais soumettre au projet d'origine

Pour ce faire, je:

  1. créé une nouvelle branche de la SHA où le projet original a été bifurqué
  2. tout tiré du projet d'origine
  3. cerise a choisi le commit que je voulais soumettre en tant que pull request
  4. poussé le tout jusqu'à github

Les commandes git étaient quelque chose comme:

  1. git branch my-feature-request 9685770
  2. git checkout ma-fonctionnalité-demande
  3. git pull https://github.com/original_project/original_project.git
  4. git cherry-pick b67627b
  5. git push origin my-feature-request

Ensuite, j'ai choisi my-feature-request comme branche de ma demande d'extraction vers le projet d'origine.

John Naegle
la source
6

Cela a presque fonctionné pour moi:

git checkout -b upstream upstream/master

git cherry-pick <SHA hash of commit>

git push origin upstream

La seule différence était la suivante:

git push origin upstream:upstream

Je devais changer cette dernière ligne pour que git push fasse la branche en amont dans mon référentiel GitHub afin que je puisse en faire PR.

hi_tech_lowlife
la source
5

J'avais déjà fait le commit que je voulais pouvoir isoler en tant que pull request sur la branche courante.

J'ai donc vérifié une nouvelle branche

git checkout -b isolated-pull

Et voici où ma solution diffère de celle de @Kevin Hakanson , car je dois réinitialiser cette branche à l'endroit de l'histoire dont je veux me différencier

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

Et choisissez le commit à partir duquel je veux créer une demande de tirage isolée

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

Enfin, poussez-le vers la télécommande

git push origin isolated-pull

Et tirez la demande dat shi.

irbanana
la source
1

La solution pour créer une nouvelle branche (temporaire), choisir la cerise sur le gâteau et créer la demande d'extraction pour cette branche ne m'a pas satisfait. Je ne voulais pas modifier mon référentiel pour rendre un ensemble de validations disponibles, j'ai donc proposé l'alternative suivante:

Créez d'abord des fichiers de correctifs pour tous les commits d'intérêt:

git format-patch -1 <sha>

Si l'engagement d'intérêt est le dernier que vous pouvez utiliser à la HEADplace <sha>.

Maintenant, vous pouvez envoyer les correctifs au responsable du référentiel source, qui peut les appliquer:

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

Enfin, cela devrait avoir la même apparence que si une branche temporaire était fusionnée par une requête pull, mais sans avoir cette branche supplémentaire dans le fork-repository.

Johannes Jendersie
la source
0

Sur la base de la réponse de @ kevin-hakanson, j'ai écrit ce petit script bash pour faciliter ce processus. Il ajoutera le référentiel en amont s'il n'existe pas déjà (vous demandant l'URL), puis demandera à la fois le nom de la nouvelle branche à créer et la balise / SHA du commit to cherry pick sur cette branche. Il vérifie sur quelle branche ou validation vous êtes actuellement, puis stocke toutes les modifications afin que vous puissiez extraire la nouvelle branche. La stratégie de fusion conserve les modifications de la validation sélectionnée. Après avoir poussé la nouvelle branche vers origin(supposé être le nom de votre dépôt distant), la branche ou la validation sur laquelle vous vous trouviez auparavant est à nouveau extraite et vos modifications précédentes sont sorties de la cachette.

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

(Cela a fonctionné pour moi dans quelques tests simples, mais je ne suis pas un programmeur bash ou un expert git, alors faites-moi savoir s'il y a des cas que j'ai ratés qui pourraient être mieux automatisés!)

Nathan
la source