Usamos o git e temos uma filial principal e uma filial do desenvolvedor. Preciso adicionar um novo recurso e depois refazer as confirmações para mestre, e depois enviar o mestre para o servidor de CI.
O problema é que, se eu tiver conflitos durante a reformulação, não poderei enviar para minha ramificação de desenvolvedor remoto (no Github) após a conclusão da rebase, até puxar minha ramificação remota. Isso causa confirmações duplicadas. Quando não há conflitos, funciona como esperado.
pergunta: após o rebase e a resolução de conflitos, como sincronizar minhas ramificações de desenvolvedor local e remota sem criar confirmações duplicadas
Configuração:
// master branch is the main branch
git checkout master
git checkout -b myNewFeature
// I will work on this at work and at home
git push origin myNewFeature
// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master
// we have conflicts
// solve conflict
git rebase --continue
//repeat until rebase is complete
git push origin myNewFeature
//ERROR
error: failed to push some refs to '[email protected]:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
// do what git says and pull
git pull origin myNewFeature
git push origin myNewFeature
// Now I have duplicate commits on the remote branch myNewFeature
EDITAR
Parece que isso interromperá o fluxo de trabalho:
developer1 trabalhando em myNewFeature developer2 trabalhando em hisNewFeature ambos usam master como ramificação principal
developer2 funde myNewFeature em hisNewFeature
developer1 rebase, resolve conflitos e força os push para ramificação remota para myNewFeature
alguns dias depois, o developer2 mescla myNewFeature no hisNewFeature novamente
Isso fará com que os outros desenvolvedores detestem o developer1?
we
? você está em uma equipe de mais do que apenas você?they
diga (as pessoas que sabem mais do que eu) que, se você compartilhar seu código, não deverá usá-lorebase
. Por que você não está apenas fazendogit pull
egit merge
?force
o push)rewriting history
, isso é umrebase
Respostas:
Primeiro, você e aqueles com quem trabalha precisa concordar se um ramo de tópico / desenvolvimento é para desenvolvimento compartilhado ou apenas para você. Outros desenvolvedores sabem que não devem ser mesclados nos meus ramos de desenvolvimento, pois serão reformulados a qualquer momento. Normalmente, o fluxo de trabalho é o seguinte:
Para manter-se atualizado com o controle remoto, faça o seguinte:
Eu Faço Isso Por Duas Razões. Primeiro porque me permite ver se há alterações remotas sem precisar mudar do meu ramo de desenvolvimento. Segundo, é um mecanismo de segurança para garantir que eu não substitua nenhuma alteração não armazenada / confirmada. Além disso, se eu não conseguir avançar rapidamente com a ramificação mestre, isso significa que alguém rebasou o mestre remoto (para o qual eles precisam ser açoitados severamente) ou acidentalmente me comprometi a dominar e preciso limpar meu objetivo.
Então, quando o controle remoto tiver alterações e eu tiver encaminhado rapidamente para a versão mais recente, refiz o seguinte:
Outros desenvolvedores sabem que precisam refazer suas ramificações de desenvolvimento das minhas últimas:
O que resulta em um histórico muito mais limpo:
Não mescle commits de um lado para o outro ao seu capricho. Ele não apenas cria confirmações duplicadas e impossibilita o acompanhamento do histórico, é quase impossível encontrar regressões de uma alteração específica (é por isso que você está usando o controle de versão em primeiro lugar, certo?). O problema que você está tendo é o resultado de fazer exatamente isso.
Também parece que outros desenvolvedores podem estar comprometendo seus ramos de desenvolvimento. Você pode confirmar isso?
O único momento para mesclar é quando o ramo do tópico está pronto para ser aceito
master
.Em uma nota lateral. Se vários desenvolvedores estão se comprometendo com o mesmo repositório, todos devem considerar nomear branches para distinguir entre desenvolvedores que desenvolvem branches. Por exemplo:
Portanto, todos os ramos de tópicos dos desenvolvedores residem em seu próprio conjunto aninhado.
fonte
--force
bandeira quando usagit push -f origin devel0
?git push
não é possível avançar rapidamente (ou seja, o histórico sha não corresponde), você deve forçar push para substituir o histórico anterior pelo novo histórico gerado a partir dogit rebase
.Você precisa forçar o push à medida que moveu as confirmações mais abaixo na linha que o git espera que você adicione confirmações na ponta do ramo.
git push -f origin myNewFeature
vai resolver o seu problema.Dica: Acima está um uso legítimo de força forçada. Nunca reescreva a história em um repositório acessível ao público ou muitas pessoas o odiarão.
fonte
git push --force-with-lease
é muito mais seguro do que usar #git push --force
git push --force-with-lease origin HEAD
- assumindo que o seu ramo de destino já está checkoutedA principal coisa a ter em mente aqui é o que puxar e rebater estão fazendo nos bastidores.
Um puxão basicamente faz duas coisas: buscar e mesclar. Quando você incluir --rebase, ele fará uma nova recuperação em vez da mesclagem.
Uma rebase é praticamente como esconder todas as suas alterações locais desde que você ramificou, encaminhando rapidamente sua ramificação para a confirmação mais recente no destino e removendo as alterações na ordem em cima.
(Isso explica por que você pode receber vários prompts de resolução de conflitos ao fazer uma nova atualização versus a única solução de conflito que você pode obter com uma mesclagem. Você tem a oportunidade de resolver um conflito no EACH commit que está sendo reformulado para preservar seus commits. )
Você nunca deseja enviar alterações reformuladas para ramificações remotas, pois isso está reescrevendo o histórico. Ofcoarse, nunca é um pouco forte, pois quase sempre há exceções. O caso em que você precisa manter uma versão remota do seu repositório local para trabalhar em um ambiente específico, por exemplo.
Isso exigirá que você faça alterações rebaseadas às vezes usando força:
Em alguns casos, seu administrador pode ter removido a capacidade de forçar, então você deve excluir e recriar:
Em ambos os casos, você deve ter certeza absoluta de que sabe o que está fazendo se outra pessoa estiver colaborando com você em sua filial remota. Isso pode significar que você trabalha em conjunto inicialmente com mesclagens e as redimensiona para um formato de confirmação mais gerenciável antes de dominar e remover sua ramificação de trabalho.
Lembre-se de que você quase sempre pode usar o GC do git aproveitando:
Este é um enorme salva-vidas, pois você pode voltar a um estado mais estável se se perder em todo o gerenciamento de rebase / conflito.
fonte
Você precisa executar um empurrão forçado, ou seja,
git push -f origin myNewFeature
Ah, e é melhor você ter certeza de que as pessoas não baseiam nada no seu ramo de desenvolvimento - normalmente você não deve publicar ramos nos quais você está reescrevendo o histórico (ou melhor, não reescreva o histórico uma vez publicado). Uma maneira seria usar um nome de filial como
wip/myNewFeature
e, em seguida, mencionar que aswip
ramificações serão reformuladas para dominar de tempos em tempos.fonte
git push --force-with-lease
é muito mais seguro do que usargit push --force
-f
para um empurrão forçado normal :)A resposta geral que já foi dada - a ser usada
git push -f origin myNewFeature
ao pressionar alterações reformuladas - é um bom ponto de partida. Estou escrevendo esta resposta para abordar a edição sobre se isso interromperá seu fluxo de trabalho.Se assumirmos que você está indo usar
git pull --rebase ...
(ou alguma variação sobre isso) seguido por uma força-push para o ramo remoto, então a única coisa que quebra o fluxo de trabalho no seu exemplo é developer2 está se fundindomyNewFeature
emhisNewFeature
. Faz sentido poder refazer sua própria ramificação de recurso, desde que ninguém mais esteja trabalhando nessa ramificação, portanto, você precisa de regras para demarcar o território da ramificação.Você pode contornar isso: a) estabelecendo uma regra da qual você apenas se une
master
; ou b) criando umdevelop
ramo coletivo , no qual você baseia o seu própriomyNewFeature
ramo, e estabelece uma regra da qual você apenas se unedevelop
.master
será reservado apenas para marcos ou liberações (ou de qualquer outra forma que você desejar configurar) edevelop
será onde você empurrará cada recurso quando estiver pronto para ser integrado a outras ramificações de recursos.Acredito que isso possa ser considerado uma versão simplificada do fluxo de trabalho do Gitflow.
fonte
Concordo com MrCholo , e talvez Trevor Norris possa considerar atualizar sua boa resposta para substituir
com
fonte