back to top

Cancellare, rinominare, spostare dei file e annullare delle modifiche in Git

In questa lezione illustreremo alcune delle operazioni più comuni che è spesso necessario effettuare durante un progetto come cancellare, spostare, rinominare o ripristinare una versione precedente di un file. Vedremo inoltre come modificare l’ultimo commit presente nel repository.

Cancellare un file in git

Ovviamente se un file è nello stato ‘Untracked’, possiamo semplicemente cancellare il file visto che non è ancora presente nella Staging Area o nel repository.

[ cancellare_dei_file_in_git ] (master) $ touch mete_turistiche_dicembre.txt
[ cancellare_dei_file_in_git ] (master) $ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

  mete_turistiche_dicembre.txt

nothing added to commit but untracked files present (use "git add" to track)
[ cancellare_dei_file_in_git ] (master) $ rm mete_turistiche_dicembre.txt
[ cancellare_dei_file_in_git ] (master) $ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Se invece il file che vogliamo eliminare è presente nella Staging Area, possiamo usare il comando git rm. Bisogna prestare attenzione perché il comando git rm non si limita a rimuovere un file dalla Staging Area, ma lo cancella anche dalla Working directory. Se vogliamo rimuovere un file solo dalla Staging Area possiamo usare l’opzione –cached.

Vediamo un esempio in cui abbiamo inizialmente il file mete_turistiche_dicembre.txt nella Working Area e nella Staging Area.

cancellare file con git rm esempio 1

Se a questo punto eseguiamo il comando git rm –cached mete_turistiche_dicembre.txt, rimuoviamo il file dalla Staging Area.

# git status prima del comando git rm --cached
[ cancellare_dei_file_in_git ]  (master ) $ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

  new file:   mete_turistiche_dicembre.txt

# esecuzione del comando git rm --cached
[ cancellare_dei_file_in_git ]  (master ) $  git rm --cached mete_turistiche_dicembre.txt
rm 'mete_turistiche_dicembre.txt'

# git status dopo l'esecuzione del comando git rm --cached
[ cancellare_dei_file_in_git ]  (master ) $ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

  mete_turistiche_dicembre.txt

nothing added to commit but untracked files present (use "git add" to track)
cancellare file con git rm esempio 1 dopo comando git rm --cached

Partendo dallo stato corrente in cui il file mete_turistiche_dicembre.txt è nello stato Untracked, proviamo ad aggiungere nuovamente il file alla Staging Area e eseguiamo il comando git rm.

[ cancellare_dei_file_in_git ]  (master ) $  git add mete_turistiche_dicembre.txt
[ cancellare_dei_file_in_git ]  (master ) $  git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

  new file:   mete_turistiche_dicembre.txt

[ cancellare_dei_file_in_git ]  (master ) $ git rm  mete_turistiche_dicembre.txt
error: the following file has changes staged in the index:
    mete_turistiche_dicembre.txt
(use --cached to keep the file, or -f to force removal)

Git ci avverte che il file è nella Staging Area, ma non è essendo stato aggiunto al repository, se eseguiamo git rm rischiamo di perdere il file per sempre visto che questo viene rimosso anche dalla Working Area. Se vogliamo comunque cancellarlo, dobbiamo usare l’opzione -f, altrimenti possiamo eseguire il commit e ripetere il comando git rm.

[ cancellare_dei_file_in_git ]  (master ) $ git commit -m 'Aggiunge il file  mete_turistiche_dicembre.txt'
[master (root-commit) a0ffe74] Aggiunge il file  mete_turistiche_dicembre.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 mete_turistiche_dicembre.txt

[ cancellare_dei_file_in_git ]  (master ) $ git rm mete_turistiche_dicembre.txt
rm 'mete_turistiche_dicembre.txt'
# la cartella è ora vuota visto che il file 
# mete_turistiche_dicembre.txt è stato cancellato dalla Working Area
[ cancellare_dei_file_in_git ]  (master ) $ ls
cancellare file con git rm esempio 2

Possiamo ora eseguire un nuovo commit, creando nel repository un nuovo snapshot nel quale salviamo le ultime modifiche subite dalla Working directory in seguito alla rimozione del file mete_turistiche_dicembre.txt.

[ cancellare_dei_file_in_git ]  (master ) $ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  deleted:    mete_turistiche_dicembre.txt
[ cancellare_dei_file_in_git ]  (master ) $ git commit -m 'Cancella il file mete_turistiche_dicembre.txt'
cancellare file con git rm esempio 2 dopo commit

Nell’immagine in alto abbiamo raffigurato con uno schema cosa succede dopo aver eseguito il commit. Abbiamo semplificato la rappresentazione del repository, mostrando solo lo stato dell’ultimo commit.

Rimuovere file Untracked dalla Working Directory

Il comando git clean può essere usato invece per rimuovere i file Untracked dalla Working Directory. Può risultare particolarmente utile quando sono presenti diversi file da rimuovere e non si vuole procedere manualmente. Vediamo un esempio in cui creiamo 10 file in una cartella che sono nello stato ‘Untracked’ non avendoli ancora aggiunti alla Staging Area.

[test_git_clean] (master) $ for i in {0..9}; do touch file_${i}; done
[test_git_clean] (master) $ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

  file_0
  file_1
  file_2
  file_3
  file_4
  file_5
  file_6
  file_7
  file_8
  file_9

nothing added to commit but untracked files present (use "git add" to track)
[test_git_clean] (master) $ git clean -n
Would remove file_0
Would remove file_1
Would remove file_2
Would remove file_3
Would remove file_4
Would remove file_5
Would remove file_6
Would remove file_7
Would remove file_8
Would remove file_9

Se eseguiamo il comando git clean con l’opzione -n o –dry-run, vengono elencati i file che verrebbero cancellati se lanciassimo il comando con l’opzione -f. Usando l’opzione -d vengono cancellate anche le cartelle ‘Untracked’.

[test_git_clean] (master) $ git clean -f
Removing file_0
Removing file_1
Removing file_2
Removing file_3
Removing file_4
Removing file_5
Removing file_6
Removing file_7
Removing file_8
Removing file_9

Spostare o rinominare dei file in Git

Vediamo ora un metodo per rinominare o spostare dei file in Git. Supponiamo di essere nella situazione in cui abbiamo all’interno di una cartella il file mete_turistiche_dicembre.txt che abbiamo precedentemente aggiunto alla Staging Area e al repository. Supponiamo di rinominare il file attraverso il comando mv come mostrato sotto.

[ rinominare_dei_file_in_git ] (master) $ mv mete_turistiche_dicembre.txt  
mete_turistiche_gennaio.txt
rinominare un file in git
[ rinominare_dei_file_in_git ] (master) $  git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

  deleted:    mete_turistiche_dicembre.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

  mete_turistiche_gennaio.txt

no changes added to commit (use "git add" and/or "git commit -a")

Dopo aver rinominato il file, Git pensa che il vecchio file è stato cancellato e un nuovo file, ancora non aggiunto alla Staging Area, è stato creato. Procediamo col rimuovere dalla Staging Area il vecchio file.

[ rinominare_dei_file_in_git ] (master) $ git rm --cached mete_turistiche_dicembre.txt
rm 'mete_turistiche_dicembre.txt'
[ rinominare_dei_file_in_git ] (master) $ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  deleted:    mete_turistiche_dicembre.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

  mete_turistiche_gennaio.txt

A questo punto, ci sono delle modifiche pronte per essere inserite nel repository. Proseguiamo invece e aggiungiamo il file rinominato nella Staging Area.

[ rinominare_dei_file_in_git ] (master) $ git add mete_turistiche_gennaio.txt
[ rinominare_dei_file_in_git ] (master) $ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  renamed:    mete_turistiche_dicembre.txt -> mete_turistiche_gennaio.txt

Git si accorge a questo punto che abbiamo sempicemente cambiato il nome del file e possiamo inserire nel repository un nuovo commit con il file appena rinominato.

[ rinominare_dei_file_in_git ] (master) $ git commit  
  -m 'Rinomina mete_turistiche_dicembre.txt in mete_turistiche_gennaio.txt'
[master 4255078] Rinomina mete_turistiche_dicembre.txt in mete_turistiche_gennaio.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename mete_turistiche_dicembre.txt => mete_turistiche_gennaio.txt (100%)
 
[ rinominare_dei_file_in_git ] (master) $ git status
On branch master
nothing to commit, working tree clean
stato del repository dopo aver rinominato il file e eseguito il commit

Se la procedura appena vista può risultare lunga, possiamo usare il comando che Git mette a disposizione git mv <file> <nuovo_file>. Dovremo poi comunque effettuare il commit per salvare nel repository uno snapshot con le modifiche effettuate.

Primo contatto con il comando git checkout

Introduciamo il comando git checkout di cui riparleremo quando affronteremo l’argomento dei Branch. Tale comando può essere usato per diversi scopi. In questo caso vediamo due casi particolari. Vediamo innanzitutto come utilizzarlo per ripristinare un file dalla staging area nella working directory. Supponiamo di avere un file ciao.txt e aggiungiamolo alla Staging Area e poi al repository.

[ test_git_checkout ]  (master) $ touch ciao.txt
[ test_git_checkout ]  (master) $ git add .
[ test_git_checkout ]  (master) $ git commit -m 'first commit'
[ test_git_checkout ]  (master) $ echo ciao > ciao.txt
[ test_git_checkout ]  (master) $ git add ciao.txt
[ test_git_checkout ]  (master) $ echo 'ciao di nuovo' >> ciao.txt

Mostriamo con un’immagine lo stato corrente della Working Directory, della Staging Area e del Repository.

ripristinare file da staging area

A questo punto eseguiamo il seguente comando:

[ test_git_checkout ]  (master) $ git checkout -- ciao.txt
[ test_git_checkout ]  (master) $ cat ciao.txt 
ciao

Abbiamo così ripristinato nella working directory il file ciao.txt dalla Staging Area in cui è comunque rimasto lo stesso file, pronto per il prossimo commit.

Il simbolo ‘–‘ (doppio dash), usato nel comando git checkout, viene usato per convenzione per indicare a Git che quello che segue è il nome di un file e non il nome di un Branch. Infatti, come vedremo possiamo usare git checkout per spostarci da un Branch all’altro.

Un’altra possibilità fornita da git checkout è quella di ripristinare nella working directory e nella staging area il contenuto di un determinato file salvato all’interno di un commit del repository.

$ git checkout <commit> elenco_file

Git copierà i file passati come argomento dal commit specificato all’interno della staging area e working directory.

git checkout file da commit

Facendo riferimento all’immagine sopra, il comando lanciato potrebbe essere simile a quello riportato sotto.

$ git checkout 39d73 file.js

Avremmo potuto anche usare il riferimento HEAD al posto di un commit.

# esempio
$ git checkout HEAD file.js

In quest’ultimo caso verrebbe ripristinato il valore del file.js dall’ultimo commit del repository, ovvero quello a cui punta il branch master referenziato da HEAD.

Correggere l’ultimo commit con git commit –amend

Il comando git commit con l’opzione –amend permette di modificare l’ultimo commit. Può capitare infatti di voler creare un unico commit che comprenda i file presenti nell’ultimo e quelli aggiunti successivamente alla Staging Area. Oppure può essere necessario modificare per qualche motivo il messaggio dell’ultimo commit. Vediamo un esempio in cui creiamo un file ciao.txt che aggiungiamo nel repository.

$ echo ciao > ciao.txt
$ git add .
$ git commit -m 'Aggiunge un file'
[master (root-commit) 2122c0e] Aggiunge un file
 1 file changed, 1 insertion(+)
 create mode 100644 ciao.txt
$ git log --oneline
2122c0e (HEAD -> master) Aggiunge un file

Supponiamo a questo punto di creare un nuovo file hello.txt e di volerlo incorporare nello stesso commit del file precedente. Modifichiamo inoltre il messaggio dell’ultimo commit.

$ echo hello > hello.txt
$ git add .
$ git commit --amend -m 'Aggiunge i file ciao.txt e hello.txt'
[master 7fa2a92] Aggiunge i file ciao.txt e hello.txt
 2 files changed, 2 insertions(+)
 create mode 100644 ciao.txt
 create mode 100644 hello.txt
$ git log --oneline
7fa2a92 (HEAD -> master) Aggiunge i file ciao.txt e hello.txt
# git ls-tree elenca il contenuto di un oggetto di tipo Tree
# in questo caso elenca il contenuto dell'oggetto Tree a cui punta il commit
$ git ls-tree 7fa2a92
100644 blob 887ae9333d92a1d72400c210546e28baa1050e44  ciao.txt
100644 blob ce013625030ba8dba906f756967f9e9ca394464a  hello.txt
git commit amend

Ricordiamo che ogni commit è identificato da un valore di hash univoco. Per questo motivo non è possibile modificare il vecchio commit, ma ne viene creato uno nuovo contenente entrambi i file. Il vecchio commit sarà poi eliminato dal garbage collector dopo un certo lasso di tempo.

Concludiamo dicendo che è anche possibile usare l’opzione –no-edit se si vogliono apportare le modifiche senza cambiare il messaggio del commit.

Conclusioni

In questa lezione abbiamo visto come cancellare dei file in git con i comandi git rm e git clean. Abbiamo poi illustrato come spostare o rinominare un file. Abbiamo mostrato un possibile uso del comando git checkout e infine abbiamo visto come correggere l’ultimo commit effettuato attraverso l’opzione –amend del comando git commit. Nella prossima lezione vedremo quali strumenti vengono messi a disposizione da Git per far in modo che un file non venga tracciato e quindi venga ignorato da Git stesso.

Pubblicità