Wednesday, September 27, 2017

Git Undo

Tulisan ini adalah kelanjutan dari tulisan sebelumnya tentang bekerja dalam tim dengan Git disini. By default, git tidak memiliki fitur git undo karena sebenarnya fitur utama dari git adalah kemampuannya untuk meng-undo secara tak terbatas. Cara meng-undo-nya bergantung pada treatment apa yang sudah anda lakukan: mengundo commit, atau kembali pada versi sebelumnya (misal: karena anda tidak puas pada versi sekarang). Berikut caranya.

A post shared by Bagus Tris Atmaja (@bagustris) on

Meng-undo comit

Misal, anda memiliki file seperti ini pada direktori repo anda,
$ pwd
/tmp/planets
$ git init
$ echo "this is earth" >> earth.txt
$ git add ./*
$ git commit -m "first commit"
$ ls
earth.txt  
$ git ls-files
earth.txt

Kemudian anda membuat file venus.txt and jupyter.txt dan mengedit file tersebut dengan isi sebagai berikut:
$ cat venus.txt
ini adalah venus
$ cat jupyter.txt
iki jupiter

Kemudian anda memutuskan untuk meng-commit dengan pesan "nambah venus dan jupyter" namun lupa menyertakan file "jupyter.txt". Berikut skrip-nya.
$ git add venus.txt
$ git commit -m "nambah venus dan jupyter"
Nah, untuk menambahkan file yang kelupaan dan meng-undo commit maka gunakan option "--amend" pada commit sehingga menjadi "git commit --amend" sebagai berikut,
$ git add jupyter.txt
$ git commit --amend
[master 8b535f8] nambah venus dan jupyter
 Date: Tue Aug 1 22:21:05 2017 +0700
 2 files changed, 2 insertions(+)
 create mode 100644 jupyter.txt
 create mode 100644 venus.txt

Anda bisa mengganti pesan commit saat meng-commit dengan option "--amend". Commit terakhir (via --ammend) akan merevisi commit sebelumnya sehingga pada "git log" hanya menampilkan satu commit untuk kasus tersebut (nambah jupyter venus).

Undo ke commit/branch sebelumnya

Misalnya dalam suatu perjalanan Git anda ingin kembali ke commit sebelumnya. Contoh, karena head saat ini ternyata corrupt, jadi anda ingin kembali ke stage sebelumnya. Untuk mengecek branch/commit mana yang ingin dituju (kembali kesitu), gunakan git log.
$ git log 
Contoh outputnya adalah sebagai berikut:
commit 33bc8dfe05669743d11ef9102e9d40ea36fa8a3e
Author: bagustris 
Date:   Wed Aug 8 10:40:50 2018 +0900

        modified:   Music_genre_classification.ipynb
        modified:   Music_genre_classification2.ipynb
        modified:   Music_genre_classification3.ipynb

commit 2f995570e95b7fc79a8d0da790d1529cbd6fc023
Author: Bagus Tris Atmaja 
Date:   Tue Aug 7 23:17:27 2018 +0900

    updata link dataset

commit 8b95781d9ef2a49ebe0ab3bb2a2efe0ba29a5686
Merge: a7ec8c4 7ed1cd0
Author: bagustris 
Date:   Tue Aug 7 23:12:57 2018 +0900

    Merge branch 'master' of https://github.com/bagustris/DL_MIR_Tutorial2

commit a7ec8c477b0984fae3410934939c2ba7456e6813

Jika ingin kembali ke commit a7ec (paling bawah), maka kita checkout ke commit tersebut. Namun sebelumnya perlu kita stash commit saat ini agar bisa kembali lagi ke commit sekarang bila terjadi kekeliruan.
$ git stash
git checkout a7ec .

Tanda titik pada baris kedua diatas sangat penting, artinya kita meng-checkout branch a7ec (cukup ketikkan 4 karakter pertama) ke direktori saat ini. Kemudian jalankan git commit tanpa argumen.
$ git commit

Git akan memberitahukan/menanyakan file mana saja yang akan di-commit, hilangkan tanda # untuk meng-commit file tersebut. Selain dengan nama bracnh, kita juga bisa menggunakan, misal, HEAD~3, untuk kembali ke tiga commit sebelumnya.

Unstaging a Staged File

Seperti yang telah dibahas di sini. Status dari sebuah file dalam siklus git dibagi menjadi empat: untracked, unmodified, modified, staged. Jika sebuah file sudah pada tahap staged, maka file tersebut akan berada baik pada master (upstream) maupun origin. Skrip berikut mendemokan bekerja pada staging area dan perubahannya pada working directory. Hal yang menarik adalah: perintah yang digunakan pada kedua area tsb (stage dan working directory) juga digunakan untuk meng-undo perubahannya. Sebagai contoh, kita merubah dua file dan ingin meng-commit-nya sebagai dua perubahan, tapi kita mengetik `git add *` yang menambahkan keduanya dan menjadikan keduanya pada tahap `stage`. Bagaimana cara meng-unstage satu dari dua file tersebut..? Cek dengan git status seperti berikut.
$ git add *
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)

renamed:    README.md -> README
modified:   CONTRIBUTING.md
Di bawah tulisan “Changes to be committed”, Git menyarankan untuk menggunakan "git reset HEAD ... to unstage". Mari kita kerjakan saran dari Git ini untuk meng-unstage file CONTRIBUTING.md:

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)

renamed:    README.md -> README

Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)

modified:   CONTRIBUTING.md
Perintah ini terlihat aneh, tapi it works!. File CONTRIBUTING.md dimofifikasi tapi masih pada tahap unstaged.

Jika kita ingin menghapus file/direktori dari repository, tapi tetap menginginkannya ada pada komputer,  gunakan perntah berikut.
git rm --cached NAMA-FILE-YANG-DIHAPUS

Note

Perintah `git reset` bisa menjadi sangat berbahaya, terutama jika ditambkan flag `--hard`. Bagaimanapun, seperti yang telah didemokan di atas, file di working directory tidak disentuh sama sekali, yang artinya apa yang kita kerjakan relatif aman.

Mulai sekarang yang perlu anda fahami adalah perintah `git reset`. Untuk memahami perintah `git reset`, kita perlu menggunakannya dan menguasai penggunaanya.

Unmodifying a Modified File

Kasus selanjutnya, bagaima jika kita ingin menyimpan perubahan pada file `CONTRIBUTING.md`?
Bagaimana caranya dengan mudah untuk tidak momodifikasinya -- mengembalikannya pada commit terakhir (atau commit pertama saat pertama kali dibuat) ? Untungnya, git memberitahu kita status dari apa yang telah kita lakukan. Misalnya pada output contoh terakhir, unstaged terlihat seperti ini.
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)

modified:   CONTRIBUTING.md
Git status memberi tahu kita secara eksplisit bagaimana untuk mengabaikan perubahan pada file di current directory. Mari kita lakukan apa yang disarankan git.
$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)

renamed:    README.md -> README

Sekarang file CONTRIBUTING.md telah kembali ke bentuk sebelumnya.

IMPORTANT

Sangat penting untuk mengetahui bahwa `git checkout --` juga merupakan perintah yang berbahaya. Perubahan yang anda lakukan pada file akan diabaikan oleh git, misal `git checkout -- namafile`. Git akan mereplace file lama dan mengganti file baru dengan file lama. Jangan pernah menggunakan perintah ini kecuali anda mengetahui dengan pasti apa yang anda lakukan dan tidak inginkan pada file.

Jika anda ingin menyimpan perubahan pada file yang anda but namun ingin menyimpannya dengan cara yang berbeda, maka yang anda butuhkan adalah: git stashing dan git branching. Mengenai git branching bisa anda baca disini, http://www.bagustris.tk/2017/04/bekerja-dalam-tim-dengan-git-di-bibucket.html.

Yang perlu diingat, apapun yang telah di-commit di Git dapat direcover. Bahkan commit pada branch yang telah dihapus ataupun commit yang telah di-overwrite dengan opsi `--amend` juga dapat di-recovery. Bagaimanapun, file yang telah hilang dan tidak pernah di-commit (local file di komputer) tidak bisa di-recovery lagi (melalui git).

Terakhir, jika anda ingin melihat file apa saja yang akan di-push, anda bisa menggunakan perintah berikut
git diff --stat --cached origin/master
Perinta `git diff` juga bisa digunakan untuk membandingkan dua commit.

Keypoints:
  • git commit --amend
  • git checkout nomor-revisi
  • git ls-files
  • git diff
  • git reset
Related Posts Plugin for WordPress, Blogger...