Sposta il lavoro esistente e senza commit in una nuova filiale in Git


3127

Ho iniziato a lavorare su una nuova funzionalità e dopo aver programmato un po 'di codice, ho deciso che questa funzione dovrebbe essere nel suo ramo.

Come posso spostare le modifiche non confermate esistenti in un nuovo ramo e ripristinare quella corrente?

Voglio ripristinare il mio ramo attuale preservando il lavoro esistente sulla nuova funzionalità.


Lo stesso argomento interessante stackoverflow.com/q/556923/269514 ?
Gilberto

Risposte:


3643

Utilizza il seguente:

git checkout -b <new-branch>

Questo lascerà il tuo ramo attuale così com'è, crea e verifica un nuovo ramo e conserva tutte le tue modifiche. È quindi possibile mettere in scena le modifiche nei file con cui eseguire il commit:

git add <files>

e impegnarsi nella nuova filiale con:

git commit -m "<Brief description of this commit>"

Le modifiche nella directory di lavoro e le modifiche messe in scena nell'indice non appartengono ancora a nessun ramo . Questo cambia il ramo in cui finiranno queste modifiche.

Non ripristini il ramo originale, rimane così com'è. L'ultimo commit <old-branch>sarà sempre lo stesso. Quindi tu checkout -be poi commetti.


Aggiornamento 2020 / Git 2.23

Git 2.23 aggiunge il nuovo switchsottocomando nel tentativo di eliminare parte della confusione derivante dall'uso sovraccarico di checkout(cambio di rami, ripristino di file, distacco di HEAD, ecc.)

A partire da questa versione di Git, sostituisci il comando sopra con:

git switch -c <new-branch>

Il comportamento è identico e rimane invariato.


15
Solo per essere sicuro, devo impegnare la funzione incompiuta PRIMA di ripristinare il mio ramo originale? O quei file non impegnati verranno conservati indipendentemente dal commit?
Dane O'Connor,

192
Cordiali saluti: i cambiamenti nella directory di lavoro e i cambiamenti messi in scena nell'indice non appartengono a un ramo. git checkout -b <new branch>cambiamenti in cui tali cambiamenti finiranno.
Jakub Narębski

152
Se si dispone già di un ramo e desidera spostare le modifiche al ramo esistente, cassa stackoverflow.com/questions/556923/...
Chirantan

14
Se si desidera inviare il nuovo ramo al repository remoto: stackoverflow.com/questions/2765421/…
Dewayne

10
@JDSmith: le modifiche di commit NON appartengono a nessun ramo. Essi risiedono solo nella directory di lavoro git checkout ./ git reset --hardsarà unrecoverably togliere loro
Knittl

331

In alternativa:

  1. Salva le modifiche correnti in una scorta temporanea:

    $ git stash

  2. Crea un nuovo ramo basato su questa scorta e passa al nuovo ramo:

    $ git stash branch <new-branch> stash@{0}

Suggerimento: utilizzare il tasto Tab per ridurre la digitazione del nome della scorta.


51
Se l'altro ramo esiste già, puoi semplicemente passare ad esso con il checkout, quindi git stash apply.
Archonic,

6
Non capisco il suggerimento "Suggerimento: utilizzare il tasto Tab per ridurre la digitazione del nome stash". "Stash @ {0}" non è il nome? Non riesco a eseguirlo correttamente.
Herbert,

7
Perché è meglio della risposta accettata stackoverflow.com/a/1394804/754997 ?
Chris Page

10
Non capisco perché sia ​​meglio della risposta accettata digit checkout -b <new branch name>
Noitidart l'

6
Non è necessario git add -Aprima di riporre.
venerdì

48

Se hai eseguito commit sulla tua filiale principale mentre hai codificato, ma ora vuoi spostare tali commit su una filiale diversa, questo è un modo rapido:

  1. Copia la cronologia corrente su una nuova filiale, portando anche eventuali modifiche non confermate:

    git checkout -b <new-feature-branch>
    
  2. Ora forza il ramo "disordinato" originale per tornare indietro: (senza passare ad esso)

    git branch -f <previous-branch> <earlier-commit-id>
    

    Per esempio:

    git branch -f master origin/master
    

    o se hai effettuato 4 commit:

    git branch -f master HEAD~4
    

Avvertimento: git branch -f master origin/master sarà ripristinare le informazioni di verifica per quel ramo. Quindi, se hai configurato il tuo masterramo per spingere in un posto diverso da origin/masterquello, la configurazione andrà persa.

Avvertenza: esiste anche un pericolo se si rinnova dopo la ramificazione, che è descritto qui . L'unico modo per evitarlo è creare una nuova storia usando cherry-pick. Questo link descrive il metodo più sicuro e sicuro . Se hai delle modifiche non impegnate, potresti volerlogit stashall'inizio egit stash popalla fine.


6
Questo risponde a una domanda che è leggermente diversa da ciò che ha chiesto l'operazione. Ho deciso di inserire questa risposta perché è qui che Google mi ha portato mentre cercavo una risposta. La vera domanda che affronta questa situazione è qui .
joeytwiddle,

26

Lo scenario comune è il seguente: ho dimenticato di creare il nuovo ramo per la nuova funzionalità e stavo facendo tutto il lavoro nel ramo della vecchia funzione. Ho affidato tutto il "vecchio" lavoro al ramo principale e desidero che il mio nuovo ramo cresca dal "maestro". Non ho fatto un unico commit del mio nuovo lavoro. Ecco la struttura del ramo: "master" -> "Old_feature"

git stash 
git checkout master
git checkout -b "New_branch"
git stash apply

18

Se lo commetti, puoi anche scegliere il singolo ID commit. Lo faccio spesso quando inizio a lavorare in master e quindi voglio creare un ramo locale prima di passare alla mia origine /.

git cherry-pick <commitID>

C'è molto che puoi fare con cherry-pick, come descritto qui , ma questo potrebbe essere un caso d'uso per te.


2
Soluzione migliore per spostare le modifiche parziali in un nuovo ramo ... poiché puoi impegnare ciò che desideri per ora, riporre tutte le altre modifiche, controllare il ramo da cui vuoi ramificare, selezionare ciliegia che si impegni sul nuovo ramo, tornare indietro al ramo originale, ripristina a fondo un commit, quindi esegui un pop stash, aggiungi, commetti e canta alleluia.
Meredith,

1
@Meredith, haha, ya qualcosa del genere. Questo è fantastico, a meno che non pianifichi le modifiche in anticipo ... e chi lo fa;)
password

1

In realtà c'è un modo davvero semplice per farlo con GitHub Desktop ora che non credo fosse una funzionalità prima.

Tutto quello che devi fare è passare al nuovo ramo in GitHub Desktop e ti chiederà di lasciare le modifiche sul ramo corrente (che verrà nascosto) o di portare con te le modifiche nel nuovo ramo. Basta scegliere la seconda opzione, per apportare le modifiche al nuovo ramo. Puoi quindi impegnarti come al solito.

GitHub Desktop


1

Questo può essere utile per tutti gli strumenti di GIT

Comando

Cambia ramo: sposterà le tue modifiche in nuovo ramo. Quindi è possibile eseguire il commit delle modifiche.

 $ git checkout -b <new-branch>

TortoiseGit

Fare clic con il tasto destro del mouse sul repository e quindi utilizzare TortoiseGit-> Switch / Checkout

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

SourceTree

Utilizzare il pulsante "Acquista" per cambiare filiale. Vedrai il pulsante "checkout" in alto dopo aver fatto clic su un ramo. Le modifiche dal ramo corrente verranno applicate automaticamente. Quindi puoi impegnarli.

inserisci qui la descrizione dell'immagine


0

Ho usato @Robin per rispondere e elencare tutto ciò che ho fatto,

git status                               <-- review/list uncommitted changes
git stash                                <-- stash uncommitted changes
git stash branch <new-branch> stash@{1}  <-- create a branch from stash
git add .                                <-- add local changes
git status                               <-- review the status; ready to commit
git commit -m "local changes ..."        <-- commit the changes
git branch --list                        <-- see list of branches incl the one created above
git status                               <-- nothing to commit, working tree (new-branch) is clean
git checkout <old-branch>                <-- switch back

! Se il repository ha più di uno stash, vedi quale applicare al nuovo ramo:

git stash list  
  stash@{0}: WIP on ...  
  stash@{1}: WIP on ...

e ispezionare la scorta individuale,

git stash show stash@{1}

O ispeziona tutti gli stash in una volta:

git stash list -p
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.