Envie uma solicitação pull no GitHub para apenas a confirmação mais recente

280

Eu criei um projeto no github e estou fazendo alterações no meu mestre local com sucesso e avançando para a origem no github. Quero enviar uma solicitação de recebimento, mas quero incluir apenas a última confirmação. A interface do usuário de solicitação de recebimento no github.com mostra os últimos 9 confirmados e não sei como filtrar isso.

Eu estava tentando entender se eu deveria criar uma nova filial local, verificar isso e, de alguma forma, redefinir ou refazer a atualização para o upstream? Em seguida, aplique minha última confirmação do meu mestre por id para a nova ramificação local e use-a para a solicitação pull?

Estou tentando acertar os conceitos e descobrir as linhas de comando certas para fazer o que eu preciso.

Kevin Hakanson
fonte
E o que acontece se você fizer uma solicitação pull com todas as outras confirmações? Eu pensei que o git é inteligente o suficiente para ignorar (ou passar) os commits que ele já recebeu?
Jayarjo # 29/12
3
Presumivelmente, o rio acima ainda não aceitou ou não quer que os intervenientes se comprometam.
Michael Scott Cuthbert
@ jayarjo Por exemplo, fiz outras alterações que não quero enviar a montante. Mudanças no git ignoram o repositório principal, por exemplo. Nada fácil com o git.
Martin
Related: Alguns bons detalhes sobre como as solicitações de pull são diferentes em Git (o software) e GitHub (o serviço web)
RBT

Respostas:

302

Você precisa basicamente criar uma nova ramificação e escolher os commits que deseja adicionar a ela.

Nota: pode ser necessário antes dos comandos 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>

Depois, você verá uma <new-branch-name>ramificação no github, mudará para ela e poderá enviar a solicitação de recebimento com as alterações desejadas.

Kevin Hakanson
fonte
32
Também preciso git remote add upstream <git repository>e git remote updateantes de executar o git checkout -b upstream upstream / master.
plainjimbo
6
Isso funciona, mas não é como você deve fazê-lo, porque agora sua ramificação upstream e upstream / master são diferentes e sempre serão diferentes se a mesclagem de sua solicitação pull não for a primeira coisa que o upstream faz. Por esse motivo, você deve preferir fazer o stackoverflow.com/a/5256304/1904815 .
precisa saber é o seguinte
2
Para elaborar: Este não é um problema técnico, mas lógico. Quando você deseja fazer algo com o upstream (como mesclar a partir daí), é necessário adicionar uma ramificação "real-upstream" ou redefinir sua upstream (não deixando nenhuma ramificação local para sua solicitação de pull para alterações adicionais).
precisa saber é o seguinte
15
Por que diabos eu preciso de uma ramificação extra, apenas para criar um PR para uma única linha de código alterada ?! Alguém no github pensou nisso?
CodeManX 20/08/2015
2
@ JonHanna Não ... por que você precisa mesclar uma filial? Por que você não pode simplesmente mesclar um commit?
Kevin Krumwiede
57

Crie uma nova ramificação a partir da confirmação mais recente, que também está no repositório de origem:

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

Em seguida, use git cherry-pickpara obter a confirmação única para a qual você deseja a solicitação de recebimento. Se o ramo com este commit for chamado featuree o commit desejado for o último commit neste branch, isso será

git cherry-pick feature

Supondo que esse patch se aplique sem conflito, você tem agora uma ramificação para a qual pode fazer sua solicitação de recebimento.

Em uma segunda etapa, agora você precisa decidir o que fazer com sua featurefilial. Se você ainda não publicou suas alterações neste ramo, o melhor procedimento é provavelmente reestruturar esse ramo em novo ramo (e remover o último commit, se isso não for feito automaticamente por git rebase).

Lars Noschinski
fonte
Recebo esta mensagem após a escolha da cereja. nada adicionado ao commit, mas arquivos não rastreados estão presentes (use "git add" para rastrear). Tudo está no meu mestre, mas eu preciso fazer meu ramo a montante.
Kevin Hakanson
5
Se o featurejá estiver confirmado origin/master, nada acontecerá durante cherry-pick. O novo ramo deve ser de upstream/master(ou seja, a resposta de Kevin Hakanson)
ohho 31/01
26

Acabei em uma situação em que eu tinha garfado um garfo e queria enviar uma solicitação de recebimento de volta ao projeto original.

Eu tinha:

  • orignal_project
  • forked_project (criado a partir do projeto original em SHA: 9685770)
  • my_fork (criado a partir do projeto bifurcado na SHA: 207e29b)
  • um commit no meu fork (SHA: b67627b) que eu queria enviar de volta ao projeto original

Para fazer isso, eu:

  1. criou uma nova ramificação do SHA onde o projeto original foi bifurcado
  2. puxou tudo do projeto original
  3. cherry escolheu o commit que eu queria enviar como uma solicitação pull
  4. empurrou tudo para o github

Os comandos git eram algo como:

  1. ramificação git my-feature-request 9685770
  2. git checkout my-feature-request
  3. git pull https://github.com/original_project/original_project.git
  4. git cherry-pick b67627b
  5. origem git push my-feature-request

Em seguida, escolhi minha solicitação de recurso como a ramificação da minha solicitação de recebimento para o projeto original.

John Naegle
fonte
6

Isso quase funcionou para mim:

git checkout -b upstream upstream/master

git cherry-pick <SHA hash of commit>

git push origin upstream

A única diferença era esta:

git push origin upstream:upstream

Eu precisava alterar a última linha para que o git push fizesse a ramificação upstream no meu repositório do GitHub para que eu pudesse fazer PR a partir dele.

hi_tech_lowlife
fonte
5

Eu já havia feito o commit que eu queria poder isolar como uma solicitação pull de volta à ramificação atual.

Então eu verifiquei uma nova filial

git checkout -b isolated-pull

E aqui é onde minha solução difere da @Kevin Hakanson , pois preciso redefinir esse ramo para o local da história em que quero diferenciar

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

E escolha o commit a partir do qual eu quero criar uma solicitação de recebimento isolada

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

Finalmente empurre-o para o controle remoto

git push origin isolated-pull

E puxe solicitação dat shi.

irbanana
fonte
1

A solução para criar uma nova ramificação (temporária), escolher cereja e criar a solicitação de recebimento para essa ramificação não me satisfez. Eu não queria mudar meu repositório para disponibilizar um conjunto de confirmações, então criei a seguinte alternativa:

Primeiro, crie arquivos de correção para todos os commits de interesse:

git format-patch -1 <sha>

Se a confirmação de interesse passa a ser o último que você pode usar HEADem vez<sha> .

Agora, você pode enviar os patches para o mantenedor do repositório de origem, que pode aplicá-los:

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

Finalmente, isso deve parecer o mesmo que se uma ramificação temporária fosse mesclada por uma solicitação pull, mas sem a ramificação adicional no repositório de bifurcações.

Johannes Jendersie
fonte
0

Com base na resposta do @ kevin-hakanson, escrevi este pequeno script bash para facilitar esse processo. Ele adicionará o repositório upstream se ele ainda não existir (solicitando o URL) e solicitará o nome da nova ramificação a ser criada e a tag / SHA da confirmação para escolher essa ramificação. Ele verifica em qual ramificação ou confirmação você está no momento e oculta as alterações para que você possa fazer check-out da nova ramificação. A estratégia de mesclagem mantém as alterações do commit escolhido pela cereja. Depois de enviar a nova ramificação para origin(assumida como o nome do seu repositório remoto), a ramificação ou confirmação em que você esteve antes é novamente verificada e as alterações anteriores foram salvas da ocultação.

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

(Isso funcionou para mim em alguns testes simples, mas eu não sou um programador de bash ou especialista em git, então deixe-me saber se há casos que perdi que poderiam ser automatizados melhor!)

Nathan
fonte