Como posso enviar uma confirmação específica para uma remota e não as confirmações anteriores?

Respostas:

1087

Para avançar através de um determinado commit, você pode escrever:

git push <remotename> <commit SHA>:<remotebranchname>

fornecido <remotebranchname>já existe no remoto. (Caso contrário, você pode usá git push <remotename> <commit SHA>:refs/heads/<remotebranchname>-lo para criar automaticamente.)

Se você deseja enviar uma confirmação sem enviar confirmações anteriores, use primeiro git rebase -ipara reordenar as confirmações.

Geoff Reedy
fonte
66
git push <remotename> <commit SHA>:<remotebranchname>trabalho. o truque é combiná-lo com git rebase -ia mover a cometer você quer como o primeiro cometer, e especificar que comprometer-sha
dminer
29
Outra boa dica é certificar-se de copiar o SHA do commit você quer empurrar depois de fazer isso rebase -i, e não antes, como eu apenas fiz :)
estan
33
Lembre-se de que isso falhará se a ramificação remota ainda não existir. A criação da ramificação pode ser feita com git push <remotename> <commit SHA>:refs/heads/<new remote branch name>. Depois disso, pressione como a resposta descreve.
Wes Oldenbeuving
32
Por exemplo, para enviar tudo, exceto o último commit, com alguns nomes padrão git push origin HEAD~1:master.
ruído artless
3
Observe também que, se você já enviou um SHA mais tarde para essa ramificação remota, precisará forçar o envio deste. Use a -fbandeira.
21414 Ian
79

As outras respostas estão faltando nas descrições de reordenação.

git push <remotename> <commit SHA>:<remotebranchname>

enviará um único commit, mas esse commit deve ser o MAIS ANTIGO do seu local, não push, commit, para não ser confundido com o commit top, first ou tip, que são descrições ambíguas na minha opinião. A confirmação precisa da confirmação mais antiga, ou seja, a mais distante da confirmação mais recente. Se não for a confirmação mais antiga, todas as confirmações do seu SHA local mais antigo e não enviado para o SHA especificado serão enviadas. Para reordenar as confirmações, use:

git rebase -i HEAD~xxx

Após reordenar o commit, você pode enviá-lo com segurança para o repositório remoto.

Para resumir, eu usei

git rebase -i HEAD~<number of commits to SHA>
git push origin <post-rebase SHA>:master

para enviar uma única confirmação ao meu ramo principal remoto.

Referências:

  1. http://blog.dennisrobinson.name/push-only-one-commit-with-git/
  2. http://blog.dennisrobinson.name/reorder-commits-with-git/

Veja também:

  1. git: Confirmações duplicadas após rebase local seguida por pull
  2. git: Enviando confirmações únicas, reordenando com rebase, confirmações duplicadas
Samuel
fonte
3
Algumas origens podem não permitir isso, ao que parece. Por exemplo, com o GitLab, vejo 'Você não tem permissão para forçar o código push para uma ramificação protegida neste projeto.'. O que é um pouco estranho, já que eu não achava que estava forçando nada, apenas fazendo um empurrão normal. Alguma idéia de como fazer isso sem 'forçar'?
Ed Avis
1
@ Ed Shoudln't ser necessário forçar push. Parece que você tem um problema com sua configuração específica do git. Talvez você tenha passado pelo commit HEAD remoto? Não sei o que é uma ramificação protegida, parece um problema de permissão.
Samuel
1
Samuel - isso faria sentido, mas o git rebase -i mostra apenas os commits locais posteriores ao HEAD remoto, então não sei como eu poderia ter feito isso.
Ed Avis
1
Samuel - de fato, eu posso fazer empates parciais agora, então não sei o que deu errado, mas deve ter tentado enviar por push um commit não derivado do HEAD remoto de uma maneira ou de outra.
Ed Avis
1
Você disse que "git rebase -i mostra apenas os commits locais posteriores ao HEAD remoto", não acho que isso seja verdade. Eu testei e consegui me recuperar do HEAD remoto.
Samuel
25

Eu sugiro usar git rebase -i; mova o commit que você deseja enviar para o topo dos commit que você fez. Em seguida, use git logpara obter o SHA do commit rebased, verifique e pressione-o. A rebase terá assegura que todos os seus outros commit agora sejam filhos daquele que você empurrou, portanto os futuros push funcionarão bem também.

Walter Mundt
fonte
3
Você poderia dar um exemplo completo de movimento esp. re o git logpasso?
Drux
4
Digamos que você tenha 3 confirmações relativamente independentes com as mensagens "A", "B", "C" confirmadas nessa ordem e que deseja pressionar "B". 'git rebase -i' deve incluir você e o editor listando todos os três; mova B para cima e salve / saia. 'git log --pretty = oneline -n3' listará B, A, C com hashes antes de cada mensagem, com B agora por último. 'git checkout -b temp $ hash_of_B; git push 'deve empurrar B nesse ponto. Você provavelmente desejará 'git checkout -b master; git branch -d temp 'para retornar ao seu estado anterior, presumindo que você estivesse em sua filial principal local; substitua conforme aplicável.
Walter Mundt
1
Você já encontrou a "ira dos deuses git" após rebase-push-rebase? (É possível que isso aconteça também por acidente, certo?) #
060
2
Se você ler minha resposta com atenção, verá que o envio ocorre apenas após a reformulação, e o envio com nova confirmação é movido apenas acima de outros envios que ainda não foram enviados. Depois que um commit é enviado, geralmente deve ser considerado gravado; deixe-o em paz novamente no futuro. Essa técnica é apenas para que você possa classificar várias alterações locais em uma boa ordem antes de enviá-las. Se você tiver configurado o rastreamento corretamente, 'git rebase -i' sem nenhum outro argumento usará como padrão nem mesmo para mostrar confirmações enviadas, por isso é mais seguro contra acidentes do que alguns outros métodos.
Walter Mundt
21

A seleção de cereja funciona melhor em comparação com todos os outros métodos enquanto pressiona um commit específico.

A maneira de fazer isso é:

Crie uma nova ramificação -

git branch <new-branch>

Atualize sua nova ramificação com sua ramificação de origem -

git fetch

git rebase

Essas ações garantirão que você tenha exatamente as mesmas coisas que sua origem.

Escolha a cereja sha idque deseja fazer -

git cherry-pick <sha id of the commit>

Você pode obter o sha idexecutando

git log

Empurre-o para a sua origem -

git push

Corra gitkpara ver que tudo parece da maneira que você queria.

David
fonte
2
O uso git rebase -iserá a solução ideal, conforme sugerido nas soluções acima. A seleção de cereja deve ser usada apenas quando você deseja duplicar a confirmação.
Vinay Bhargav #
13

Eu acredito que você teria que "reverter" para esse commit e enviá-lo. Ou você pode se cherry-pickcomprometer em uma nova ramificação e enviá-la para a ramificação no repositório remoto. Algo como:

git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin {branch}
Josh K
fonte
9
git revert é uma péssima idéia aqui - cria um novo commit
hasen
1
@hasen: Você pode então apenas cherry-pickconfirmar o que deseja.
21410 Josh K
4
reverter e escolher a cereja são más idéias. git rebase -i é seu amigo aqui, veja a resposta de Walter Mundt abaixo.
Nicolas C
3
@ Nicolas, por que escolher uma cereja é uma má idéia?
Antoine
3
@ Antonine, normalmente você quer que sua filial fique sincronizada com a que rastreia na origem. Se você escolher, você está copiando / colando e terá que lidar com a cópia não enviada em algum momento. Se você rebase -i, "recortar e colar" e manter sua ramificação sincronizada com o controle remoto até onde deseja.
Nicolas C
0

Você também pode, em outro diretório:

  • git clone [seu repositório]
  • Substitua o diretório .git no seu repositório original pelo diretório .git do repositório que você acabou de clonar agora.
  • git add e git comprometem seu original
NunoSempere
fonte