OK, achei que era um cenário simples, o que estou perdendo?
Eu tenho um master
ramo e um feature
ramo. Faço alguns trabalhos master
, outros feature
e mais master
. Termino com algo assim (ordem lexicográfica implica a ordem dos commits):
A--B--C------F--G (master)
\
D--E (feature)
Não tenho nenhum problema para git push origin master
manter o controle remoto master
atualizado, nem com git push origin feature
(quando ativado feature
) para manter um backup remoto para o meu feature
trabalho. Até agora, estamos bem.
Mas agora eu quero me refazer feature
dos F--G
commits no master, então eu git checkout feature
e git rebase master
. Ainda bom. Agora temos:
A--B--C------F--G (master)
\
D'--E' (feature)
Problema: no momento em que desejo fazer backup da nova feature
ramificação rebaseada git push origin feature
, o push é rejeitado, pois a árvore foi alterada devido à rebasagem. Isso só pode ser resolvido com git push --force origin feature
.
Eu odeio usar --force
sem ter certeza de que preciso. Então, eu preciso disso? O rebasing implica necessariamente que o próximo push
deve ser --force
cumprido?
Esse ramo de recursos não é compartilhado com outros desenvolvedores; portanto, não tenho nenhum problema de fato com o impulso de força, não vou perder nenhum dado, a questão é mais conceitual.
git pull feature-branch
essa solicitação gerará uma nova confirmação de mesclagem (mesclando as versões remota e local da ramificação do recurso). Portanto, ou você obtém uma mesclagem desnecessária após o rebaseamento ou pressiona--force
.push --force
não é um problema) para manter o histórico de confirmações linear sem nenhuma confirmação de mesclagem.--force-with-lease
como @hardev sugeriu é uma ótima opçãoEm vez de usar -f ou --force, os desenvolvedores devem usar
Por quê? Porque ele verifica se há mudanças na ramificação remota, o que é absolutamente uma boa ideia. Vamos imaginar que James e Lisa estejam trabalhando no mesmo ramo de recursos e Lisa tenha enviado um commit. James agora repassa sua filial local e é rejeitado ao tentar empurrar. É claro que James acha que isso se deve à reformulação e uso do --force e reescreveria todas as alterações de Lisa. Se James tivesse usado --force-with-lease, ele teria recebido um aviso de que há compromissos feitos por outra pessoa. Não vejo por que alguém usaria --force em vez de --force-with-lease ao pressionar após uma rebase.
fonte
git push --force-with-lease
me salvou um monte.--force-with-lease
aborda a preocupação de usar--force
Eu usaria "checkout -b" e é mais fácil de entender.
Quando você exclui, evita enviar uma ramificação existente que contém SHA ID diferente. Estou excluindo apenas a ramificação remota neste caso.
fonte
push --force
, portanto, é apenas uma maneira de evitar um repositório Git--force
. Como tal, não acho que essa seja uma boa idéia - nem o repo permitepush --force
, nem por um bom motivo que o desativa. A resposta de Nabi é mais apropriada se--force
estiver desabilitada no repositório remoto, pois não corre o risco de perder confirmações de outros desenvolvedores ou causar problemas.Uma solução para isso é fazer o que é msysGit merge rebasing script faz - depois que o rebase, merge no antigo chefe da
feature
com-s ours
. Você acaba com o gráfico de confirmação:... e seu impulso
feature
será um avanço rápido.Em outras palavras, você pode fazer:
(Não testado, mas acho que está certo ...)
fonte
git rebase
(em vez de mesclarmaster
novamente para o ramo de recursos) é criar histórico de confirmações lineares limpas. Com sua abordagem, o histórico fica ainda pior. E como o rebasing cria novos commits sem nenhuma referência às versões anteriores, nem tenho certeza de que o resultado dessa mesclagem será adequado.merge -s ours
é que ele adiciona artificialmente uma referência pai à versão anterior. Claro, a história não parece limpa, mas o interlocutor parece estar particularmente incomodado por ter que forçar o empurrão dofeature
galho, e isso contorna isso. Se você deseja refazer a recuperação, é mais ou menos uma ou outra. :) De modo mais geral, eu acho que é interessante que o projeto msysgit faz isso ....ours
estratégia antes, mas achei que ela se aplica apenas a situações de conflito, resolvendo-as automaticamente usando alterações em nossa filial. Acabou que funciona de maneira diferente. E, dessa maneira, é muito útil se você precisar de uma versão reformulada (por exemplo, para que o mantenedor de repositórios a aplique de maneira limpamaster
), mas deseje evitar o esforço forçado (se muitas outras pessoas, por algum motivo, estiverem usando o seu ramo de recursos).Pode ou não ser o caso de haver apenas um desenvolvedor neste ramo, que agora (após o rebase) não está alinhado com a origem / recurso.
Como tal, sugiro usar a seguinte sequência:
Sim, novo ramo, isso deve resolver isso sem uma força -, o que eu acho que geralmente é uma grande desvantagem do git.
fonte
Minha maneira de evitar o empurrão forçado é criar um novo ramo e continuar o trabalho nesse novo ramo e, após alguma estabilidade, remover o ramo antigo que foi rebatizado:
fonte
Outros responderam sua pergunta. Se você refazer uma ramificação, precisará forçar a empurrá-la.
Rebase e um repositório compartilhado geralmente não se dão bem. Isso está reescrevendo o histórico. Se outras pessoas estiverem usando esse ramo ou se ramificarem nesse ramo, a recuperação será bastante desagradável.
Em geral, o rebase funciona bem para o gerenciamento de filiais locais. O gerenciamento de filial remota funciona melhor com mesclagens explícitas (--no-ff).
Também evitamos mesclar o mestre em um ramo de recurso. Em vez disso, redefinimos para master, mas com um novo nome de filial (por exemplo, adicionando um sufixo de versão). Isso evita o problema de rebasear no repositório compartilhado.
fonte
O que há de errado com um
git merge master
nofeature
ramo? Isso preservará o trabalho que você teve, mantendo-o separado da ramificação da linha principal.Edit: Ah, desculpe, não leu sua declaração de problema. Você precisará de força ao executar a
rebase
. Todos os comandos que modificam o histórico precisarão do--force
argumento. Isso é à prova de falhas para impedir que você perca o trabalho (o antigoD
eE
seria perdido).Portanto, você executou um
git rebase
que fez a árvore parecer (embora parcialmente ocultaD
eE
não esteja mais em um ramo nomeado):Então, ao tentar empurrar seu novo
feature
ramo (comD'
eE'
dentro dele), você perderiaD
eE
.fonte
Para mim, seguir etapas fáceis funciona:
Depois de fazer tudo acima, podemos excluir o ramo myFeature também seguindo o comando:
fonte
O seguinte funciona para mim:
git push -f origin branch_name
e não remove nenhum código meu.
Mas, se você quiser evitar isso, faça o seguinte:
então você pode escolher todos os seus commit no novo ramo.
git cherry-pick COMMIT ID
e depois empurre seu novo ramo.fonte
-f
é um apelido para--force
, que é o que a pergunta está tentando evitar, se possível.Como o OP entende o problema, apenas procura uma solução melhor ...
Que tal isso como uma prática?
Tenha um ramo de desenvolvimento de recursos real (onde você nunca se recupera e pressiona com força, para que seus colegas desenvolvedores de recursos não o odeiem). Aqui, pegue regularmente essas alterações do main com uma mesclagem. História mais confusa , sim, mas a vida é fácil e ninguém fica interrompido em seu trabalho.
Tenha um segundo ramo de desenvolvimento de recursos, em que um membro da equipe de recursos regularmente empurra todos os recursos comprometidos para, de fato, reestruturados e até forçados. Tão quase limpo com base em um commit mestre bastante recente. Quando o recurso estiver concluído, empurre esse ramo em cima do mestre.
Talvez já exista um nome de padrão para esse método.
fonte