Estou usando a subárvore Git com alguns projetos nos quais estou trabalhando, para compartilhar algum código base entre eles. O código base é atualizado com frequência, e as atualizações podem acontecer em qualquer um dos projetos, com todos eles sendo atualizados, eventualmente.
Eu tive um problema onde o git relata que minha subárvore está atualizada, mas o push é rejeitado. Por exemplo:
#! git subtree pull --prefix=public/shared project-shared master
From github.com:****
* branch master -> FETCH_HEAD
Already up-to-date.
Se eu empurrar, devo receber uma mensagem de que não há nada para empurrar ... Certo? CERTO? :(
#! git subtree push --prefix=public/shared project-shared master
git push using: project-shared master
To [email protected]:***
! [rejected] 72a6157733c4e0bf22f72b443e4ad3be0bc555ce -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:***'
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.
Qual poderia ser o motivo disso? Por que o push está falhando?
git
git-subtree
Mateusz
fonte
fonte
--rejoin
para acelerar os empurrões de subárvore. Quando eu passo pelo push da subárvore manualmente, executandosubtree split --rejoin
, a ramificação da subárvore dividida só tem o histórico de volta para a última reunião, quando normalmente contém todo o histórico da subárvore. Para mim, essa é a causa imediata do erro de não avanço rápido. Ainda não sei por que a divisão de subárvore está gerando um histórico truncado.Respostas:
Encontrei a resposta neste comentário de blog https://coderwall.com/p/ssxp5q
fonte
error: unknown option 'prefix'
heroku
epythonapp
ter na resposta. Traduzindo para uma linguagem específica de Heroku:git push <your subtree's origin> `git subtree split --prefix=Path/to/subtree master`:master --force
No Windows, o comando aninhado não funciona:
Você pode apenas executar o bit aninhado primeiro:
Isso (depois de muitos números) retornará um token, por exemplo
Use isso no comando de conteúdo, por exemplo:
fonte
git subtree
não é um comando antes. Depois de usar sua solução, consegui implantar uma pasta no heroku em vez de todo o meu repoUse a
--onto
bandeira:[EDITAR: infelizmente
subtree push
não encaminha--onto
para o subjacentesplit
, então a operação tem que ser feita em dois comandos! Feito isso, vejo que meus comandos são idênticos aos de uma das outras respostas, mas a explicação é diferente, então vou deixá-la aqui mesmo assim.]Ou se você não estiver usando o bash:
Passei horas estudando a fonte git-subtree para descobrir isso, então espero que você goste;)
subtree push
começa executandosubtree split
, que reescreve seu histórico de commits em um formato que deve estar pronto para envio. A maneira como ele faz isso épublic/shared/
retirando a frente de qualquer caminho que o contenha e removendo todas as informações sobre os arquivos que não o possuem. Isso significa que mesmo se você puxar não compactado, todos os commits do sub-repositório upstream são desconsiderados, pois eles nomeiam os arquivos por seus caminhos vazios. (Confirmações que não afetam nenhum arquivo sobpublic/shared/
, ou commits de mesclagem idênticos a um pai, também são reduzidos. [EDIT: Além disso, já encontrei alguma detecção de squash, então agora estou pensando que é apenas se você puxou não esmagado, e então o colapso simplista do commit de mesclagem descrito em outra resposta consegue escolher o caminho não esmagado e descartar o caminho comprimido.]) O resultado é que o material que ele tenta enviar acaba contendo qualquer trabalho que alguém tenha enviado ao repositório host atual do qual você está enviando, mas não pessoas comprometidas diretamente com o sub-repositório ou por meio de outro host repositório.No entanto, se você usar
--onto
, então todos os commits upstream são registrados como OK para usar literalmente, então quando o processo de reescrita os encontra como um dos pais de uma fusão que deseja reescrever, ele os manterá ao invés de tentar reescrevê-los da maneira usual.fonte
git remote -v
.--onto
opção ajuda o git a identificar commits que já estão no sub-repositório.Para um aplicativo do tipo "páginas do GitHub", em que você implanta uma subárvore "dist" em um branch gh-pages, a solução pode ser parecida com esta
Menciono isso porque parece um pouco diferente dos exemplos de heroku dados acima. Você pode ver que minha pasta "dist" existe no branch master do meu repo, e então eu a empurro como uma subárvore para o branch gh-pages que também está na origem.
fonte
Eu também já encontrei esse problema e aqui está como resolvi.
O que descobri foi que tinha um ramo que não estava vinculado ao ramo mestre local. Este galho existe e está apenas pendurado no vazio. No seu caso, provavelmente é chamado
project-shared
. Assumindo que este é o caso e quando você faz um,git branch
você pode ver umproject-shared
branch local , então você pode ' anexar ' novos commits ao seuproject-shared
branch existente fazendo:git subtree split --prefix=public/shared --onto public-shared --branch public-shared
Pelo que entendi,
git subtree
vou começar a criar um novo branch--onto
, neste caso é opublic-shared
branch local . Então, o ramo significa criar um ramo, que apenas substitui o antigopublic-shared
ramo.Isso manterá todos os SHA anteriores do
public-shared
ramo. Finalmente, você pode fazer umgit push project-shared project-shared:master
Supondo que você também tenha um
project-shared
controle remoto; isso irá empurrar o local pendurado noproject-shared
ramo vazio para omaster
ramo do remotoproject-shared
.fonte
Isso ocorre devido à limitação do algoritmo original. Ao lidar com mesclagem-commits, o algoritmo original usa um critério simplificado para cortar pais não relacionados. Em particular, ele verifica se há um pai, que tem a mesma árvore. Se tal pai for encontrado, ele colapsará o commit de mesclagem e usará o commit pai, assumindo que outros pais tenham mudanças não relacionadas à subárvore. Em alguns casos, isso resultaria na eliminação de partes do histórico, que apresentam mudanças reais na subárvore. Em particular, ele descartaria sequências de commits, que tocariam uma subárvore, mas resultariam no mesmo valor de subárvore.
Vamos ver um exemplo (que você pode reproduzir facilmente) para entender melhor como isso funciona. Considere o seguinte histórico (o formato da linha é: commit [tree] subject):
Neste exemplo, estamos nos dividindo
dir
. CommitsD
eE
têm a mesma árvorez
, porque temos commitC
, que desfaz o commitB
, então aB-C
seqüência não faz nadadir
mesmo que tenha alterações nela.Agora vamos dividir. Primeiro, dividimos no commit
C
.Em seguida, dividimos no commit
E
.Sim, perdemos dois commits. Isso resulta no erro ao tentar empurrar a segunda divisão, uma vez que não tem esses dois commits, que já entraram na origem.
Normalmente você pode tolerar esse erro usando
push --force
, uma vez que commits descartados geralmente não terão informações críticas neles. No longo prazo, o bug precisa ser consertado, então o histórico de divisão teria, na verdade, todos os commits, que tocamdir
, conforme o esperado. Eu esperaria que a correção incluísse uma análise mais profunda dos commits pai para dependências ocultas.Para referência, aqui está a parte do código original, responsável pelo comportamento.
fonte
A resposta de Eric Woodruff não me ajudou, mas o seguinte sim:
Eu geralmente 'git subtree pull' com a opção '--squash'. Parece que isso tornou as coisas mais difíceis de reconciliar, então eu precisei fazer uma subtree pull sem esmagar desta vez, resolver alguns conflitos e depois empurrar.
Devo acrescentar que o puxão esmagado não revelou nenhum conflito, disse-me que estava tudo bem.
fonte
Outra solução [mais simples] é avançar o controle remoto fazendo outro commit, se puder. Depois de puxar esse cabeçote avançado para a subárvore local, você poderá empurrá-lo novamente.
fonte
Você pode forçar o envio de alterações locais para o repositório de subárvore remoto
fonte
Um PowerShell rápido para usuários do Windows com base na solução de Chris Jordan
fonte
Então, isso é o que eu escrevi baseado no que @entheh disse.
fonte
Tive esse problema também. Aqui está o que eu fiz, com base nas principais respostas:
Dado:
Insira isto:
Observe que o token gerado por 'git subtree push' é usado em 'git push'.
fonte