In qualche modo il mio maestro e la mia origine / ramo principale sono divergenti.
In realtà non voglio che divergano.
Come posso visualizzare queste differenze e "unirle"?
In qualche modo il mio maestro e la mia origine / ramo principale sono divergenti.
In realtà non voglio che divergano.
Come posso visualizzare queste differenze e "unirle"?
Risposte:
Puoi rivedere le differenze con un:
git log HEAD..origin/master
prima di estrarlo (recupera + unisci) (vedi anche "Come fai ad estrarre Git da un ramo specifico?" )
Quando hai un messaggio come:
"La tua filiale e 'origine / master' sono divergenti, # e hanno 1 e 1 commit diversi ciascuno, rispettivamente."
, controlla se devi aggiornareorigin
. Se origin
è aggiornato, alcuni commit sono stati trasferiti origin
da un altro repository mentre sono stati effettuati i propri commit localmente.
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
Hai basato il commit C sul commit A perché quello era l'ultimo lavoro che avevi recuperato da upstream in quel momento.
Tuttavia, prima di provare a riportare indietro all'origine, qualcun altro ha spinto il commit B.
La storia dello sviluppo si è divisa in percorsi separati.
È quindi possibile unire o riformulare. Vedi Pro Git: Git Branching - Rebasing per i dettagli.
Merge
Usa il comando git merge:
$ git merge origin/master
Questo dice a Git di integrare le modifiche dal origin/master
tuo lavoro e creare un commit di unione.
Il grafico della storia ora appare così:
... o ---- o ---- A ---- B origin/master (upstream work)
\ \
C ---- M master (your work)
La nuova unione, commit M, ha due genitori, ognuno dei quali rappresenta un percorso di sviluppo che ha portato al contenuto archiviato in quel commit.
Si noti che la storia dietro M è ora non lineare.
rebase
Usa il comando git rebase:
$ git rebase origin/master
Questo dice a Git di riprodurre il commit C (il tuo lavoro) come se lo avessi basato sul commit B anziché su A. Gli
utenti di CVS e Subversion sistematicamente cambiano le loro modifiche locali in cima al lavoro a monte quando eseguono l'aggiornamento prima del commit.
Git aggiunge semplicemente una separazione esplicita tra i passaggi commit e rebase.
Il grafico della storia ora appare così:
... o ---- o ---- A ---- B origin/master (upstream work)
\
C' master (your work)
Commit C 'è un nuovo commit creato dal comando git rebase.
È diverso da C in due modi:
Si noti che la storia dietro C 'è ancora lineare.
Abbiamo scelto (per ora) di consentire solo la cronologia lineare in cmake.org/cmake.git
.
Questo approccio preserva il flusso di lavoro basato su CVS utilizzato in precedenza e potrebbe facilitare la transizione.
Un tentativo di spingere C 'nel nostro repository funzionerà (supponendo che tu abbia i permessi e nessuno ha spinto mentre stavi eseguendo il rebasing).
Il comando git pull fornisce un modo abbreviato per recuperare dall'origine e rifare il lavoro locale su di esso:
$ git pull --rebase
Questo combina i passaggi sopra recuperati e rebase in un solo comando.
git reset --hard HEAD
eliminerebbe solo qualsiasi modifica non impegnata indicizzata locale e non farebbe nulla per riconciliare le differenze tra commit locali e remoti . Solo un'unione o un rebase riunirà i due set di commit (quello locale e quello remoto) insieme.
master
indicare il B
tuo esempio.
git reset --hard origin/master
come accennato nella risposta appena sotto: stackoverflow.com/a/8476004/6309
Ho avuto questo e sono sconcertato da ciò che l'ha causato, anche dopo aver letto le risposte di cui sopra. La mia soluzione era fare
git reset --hard origin/master
Quindi questo reimposta la mia copia (locale) del master (che presumo sia rovinata) nel punto corretto, come rappresentato da (remoto) origin / master.
ATTENZIONE : perderai tutte le modifiche non ancora inviate
origin/master
.
git reflog
o vederli gitk --all
. Ma, naturalmente, l'hard reset è un'altra cosa che un rebase.
git pull --rebase origin/master
è un singolo comando che può aiutarti nella maggior parte dei casi.
Modificare: estrae i commit dall'origine / master e applica le modifiche sulla cronologia del ramo appena estratto.
Mi sono trovato in questa situazione quando ho provato a rebase un ramo che stava rintracciando un ramo remoto e stavo cercando di rifarlo su master. In questo scenario, se provi a rebase, molto probabilmente troverai il tuo ramo divergente e può creare un disastro che non è per git cloudes!
Supponiamo che tu sia sul ramo my_remote_tracking_branch, che è stato ramificato dal master
$ git status
# Sul ramo my_remote_tracking_branch
niente da impegnare (directory di lavoro pulita)
E ora stai cercando di tornare dal master come:
git rebase master
FERMATI ORA e risparmia qualche problema! Invece, usa unisci come:
git merge master
Sì, finirai con ulteriori impegni sulla tua filiale. Ma a meno che tu non sia interessato a rami "non divergenti", questo sarà un flusso di lavoro molto più agevole rispetto al rebasing. Vedi questo blog per una spiegazione molto più dettagliata.
D'altra parte, se il tuo ramo è solo un ramo locale (cioè non è ancora stato inviato a nessun telecomando) dovresti assolutamente fare un rebase (e il tuo ramo non divergerà in questo caso).
Ora, se stai leggendo questo perché già sono in una "divergevano" scenario a causa di tale rebase, si può tornare all'ultimo commit di origine (cioè in uno stato non discostato) utilizzando:
git reset --hard origin / my_remote_tracking_branch
rebase
se il ramo che stai riassegnando non è stato pubblicato (e utilizzato da altre persone). Altrimenti, usa merge
. Se rifatti i rami già pubblicati (e utilizzati), devi coordinare una cospirazione per riscrivere la cronologia di tutti gli sviluppatori che hanno utilizzato il tuo ramo.
git rebase master
...
git reset --hard origin/my_remote_tracking_branch
è quello che ha funzionato davvero
Nel mio caso, ecco cosa ho fatto per causare il messaggio divergente : l'ho fatto git push
ma poi ho fattogit commit --amend
aggiunto qualcosa al messaggio di commit. Poi ho anche fatto un altro commit.
Quindi nel mio caso ciò significava semplicemente che origin / master era obsoleto. Poiché sapevo che nessun altro stava toccando origin / master, la correzione era banale: git push -f
(dove -f
significa forza)
git push -f
sovrascrivere le modifiche precedentemente impegnate e trasferite all'origine. Sono anche sicuro che nessun altro abbia toccato il repository.
Nel mio caso ho apportato modifiche a origin/master
e poi ho capito che non avrei dovuto farlo :-( Questo era complicato dal fatto che le modifiche locali erano in una sottostruttura. Quindi sono tornato all'ultimo commit buono prima del "cattivo" locale cambia (usando SourceTree) e poi ho ricevuto il "messaggio di divergenza".
Dopo aver risolto il mio disordine localmente (i dettagli non sono importanti qui) volevo "tornare indietro nel tempo" il origin/master
ramo remoto in modo che fosse nuovamente sincronizzato con il locale master
. La soluzione nel mio caso era:
git push origin master -f
Notare l' -f
interruttore (force). Ciò ha eliminato le "modifiche errate" che erano state spinte per origin/master
errore e ora le filiali locali e remote sono sincronizzate.
Tieni presente che si tratta di un'operazione potenzialmente distruttiva, quindi eseguila solo se sei sicuro al 100% che "tornare indietro" in tempo il master remoto è OK.
You are not allowed to force push code to a protected branch on this project.
. Sto cercando di spingere verso la mia forchetta.
So che ci sono molte risposte qui, ma penso che git reset --soft HEAD~1
meriti qualche attenzione, perché ti consente di mantenere i cambiamenti nell'ultimo commit locale (non spinto) mentre risolvi lo stato divergente. Penso che questa sia una soluzione più versatile di quella con cui interagire rebase
, perché il commit locale può essere rivisto e persino spostato in un altro ramo.
La chiave sta usando --soft
, invece del duro --hard
. Se è presente più di 1 commit, una variante di HEAD~x
dovrebbe funzionare. Quindi, ecco tutti i passaggi che hanno risolto la mia situazione (avevo 1 commit locale e 8 commit nel telecomando):
1) git reset --soft HEAD~1
per annullare il commit locale. Per i passaggi successivi, ho usato l'interfaccia in SourceTree, ma penso che dovrebbero funzionare anche i seguenti comandi:
2) git stash
per nascondere le modifiche da 1). Ora tutti i cambiamenti sono al sicuro e non c'è più divergenza.
3) git pull
per ottenere le modifiche remote.
4) git stash pop
oppure git stash apply
applicare le ultime modifiche nascoste, seguite da un nuovo commit, se lo si desidera. Questo passaggio è facoltativo, insieme a 2) , quando si desidera eliminare le modifiche nel commit locale. Inoltre, quando si desidera eseguire il commit in un altro ramo, questo passaggio deve essere eseguito dopo il passaggio a quello desiderato.
pull --rebase
metterebbe automaticamente comunque. stackoverflow.com/a/30209750/6309
Per visualizzare le differenze:
git difftool --dir-diff master origin/master
Questo mostrerà i cambiamenti o le differenze tra i due rami. In araxis (il mio preferito) lo visualizza in uno stile diff cartella. Mostra ciascuno dei file modificati. Posso quindi fare clic su un file per vedere i dettagli delle modifiche nel file.
Nel mio caso ciò è stato causato dal fatto di non aver commesso la mia risoluzione del conflitto.
Il problema è stato causato dall'esecuzione del git pull
comando. I cambiamenti nell'origine hanno portato a conflitti con il mio repository locale, che ho risolto. Tuttavia, non li ho commessi. La soluzione a questo punto è impegnare le modifiche ( git commit
il file risolto)
Se sono stati modificati anche alcuni file dalla risoluzione del conflitto, il git status
comando mostrerà le modifiche locali come modifiche locali non in scena e unirà la risoluzione come modifiche locali in fasi. Ciò può essere risolto correttamente eseguendo prima le modifiche dall'unione git commit
, quindi aggiungendo e eseguendo le modifiche non messe in scena come di consueto (ad esempio da git commit -a
).
Avevo lo stesso messaggio quando stavo cercando di modificare l'ultimo messaggio di commit, di commit già inviato, usando: git commit --amend -m "New message"
Quando ho inviato le modifiche usando git push --force-with-lease repo_name branch_name
non c'erano problemi.
Ho riscontrato questo problema quando ho creato un ramo basato sul ramo A di
git checkout -b a
e quindi ho impostato il flusso up del ramo a sul ramo B di origine
git branch -u origin/B
Quindi ho ricevuto il messaggio di errore sopra.
Un modo per risolvere questo problema per me era,
git checkout -b b origin/B