Cara membuat hidup lebih mudah saat menggunakan Git (serta pilihan bahan untuk perendaman dalam)


Tree of Dragons II oleh surrealistguitarist

Bagi mereka yang menggunakan Git setiap hari tetapi merasa tidak aman, timMail.ru Cloud Solutions telah menerjemahkan artikel oleh pengembang front-end Shane Hudson . Di sini Anda akan menemukan beberapa trik dan kiat yang dapat membuatnya sedikit lebih mudah untuk bekerja dengan Git, serta pilihan artikel dan manual dari tingkat yang lebih maju.

Git muncul hampir 15 tahun yang lalu. Selama waktu ini, ia berubah dari underdog menjadi juara yang tak terkalahkan. Hari ini, proyek baru sering dimulai dengan tim git init. Tidak diragukan lagi, ini adalah alat penting yang banyak dari kita gunakan setiap hari, tetapi sering menyerupai sihir - cerah, tetapi berbahaya.

Banyak artikel telah dipublikasikan di Habr, cara memulai dengan Git, bagaimana Git bekerja di bawah tenda , dan deskripsi strategi percabangan terbaik. Di sini, penulis fokus pada bagaimana menyederhanakan pekerjaan dengan Git.

Kami mengatur semuanya


Maksud Git adalah menyelamatkan pekerjaan Anda, beralih konteks - dan melakukan sesuatu yang lain. Ini bisa berupa cadangan kode atau kemampuan untuk secara asinkron mengembangkan beberapa fungsi yang berbeda. Akan mengerikan untuk membuang versi kedua hanya karena kesalahan ditemukan di versi pertama. Tidak kalah memalukan untuk menyimpan file dengan nama seperti v1_final_bug_fixed. Seperti yang Anda tahu, ini menyebabkan kekacauan total.

Kita semua tahu bahwa hidup menjadi lebih mudah ketika pembaruan kami ditata dengan rapi di cabang Git yang dapat Anda bagikan dengan rekan kerja. Tetapi seringkali situasi muncul ketika Anda mengubah konteks, lalu kembali - dan Anda tidak dapat menemukan cabang yang tepat. Apakah ada komitmen sama sekali? Mungkin dia disembunyikan? Mungkin komit tidak lulus, sekarang semua orang telah pergi ke cabang yang salah, dan semuanya buruk, dan saya melakukan pekerjaan yang sangat buruk! Ya, semua orang ada di sana dan merasakan keraguan seperti itu. Ada beberapa cara untuk menghadapi situasi ini.

Sortir cabang berdasarkan tanggal


Penyortiran berdasarkan tanggal menunjukkan semua cabang lokal Anda, mulai dari yang terakhir. Cukup lumrah, tapi itu banyak membantu saya:

# To sort branches by commit date
git branch --sort=-committerdate

Utas sebelumnya


Bagaimana jika Anda tidak melakukan, beralih cabang, dan kemudian ingin kembali ke yang sebelumnya? Anda mungkin dapat menemukannya di daftar cabang jika Anda memiliki gagasan tentang namanya. Tetapi bagaimana jika itu bukan cabang, tetapi detached HEADkomitmen tertentu?

Ternyata ada jalan keluar yang sederhana:

# Checkout previous branch
git checkout -

Operator -adalah singkatan untuk sintaks @{-1}yang memungkinkan Anda untuk beralih ke sejumlah checkout kembali. Jadi, jika, misalnya, Anda membuat cabang feature/thing-a, lalu feature/thing-b, dan kemudian bugfix/thing-c, parameter @{-2}akan mengembalikan Anda ke feature/thing-a:

# Checkout branch N number of checkouts ago
git checkout @{-N}

Tampilkan informasi tentang semua cabang


Bendera vmemperlihatkan daftar semua cabang dengan pengidentifikasi dan pesan komit terakhir. Ganda vvjuga akan menampilkan cabang hulu terpencil, diikuti oleh cabang lokal:

# List branches along with commit ID, commit message and remote
git branch -vv

Mencari berkas


Kita semua jatuh ke dalam situasi ini: entah bagaimana ternyata satu file tertinggal di cabang yang salah. Apa yang harus dilakukan? Ulangi semua pekerjaan atau salin kode dari satu cabang ke cabang lain? Tidak, untungnya, ada cara untuk menemukan file tertentu.

Metode ini agak aneh, mengingat bahwa git checkout -Anda akan dibawa ke cabang sebelumnya. Secara umum, jika Anda menentukan --setelah nama cabang di checkout, ini akan memungkinkan Anda untuk menentukan file spesifik yang Anda cari. Anda tidak akan menebak fungsi seperti itu tanpa petunjuk, tetapi sangat nyaman jika Anda tahu:

git checkout feature/my-other-branch -- thefile.txt

Bersihkan status


Tomasz Lacoma tweeted tentang mengurangi penerbitan git statusdengan bantuan bendera -sbdan menambahkan: "Selama bertahun-tahun saya telah menggunakan Git, tetapi tidak ada yang memberi tahu saya tentang ini." Ini bukan hanya tentang menemukan file yang hilang. Ada saat-saat ketika menyederhanakan masalah membuatnya lebih mudah untuk melihat perubahan.

Sebagian besar perintah Git memiliki flag-flag ini, jadi Anda harus belajar bagaimana menggunakannya untuk menyesuaikan alur kerja Anda:

# Usually we would use git status to check what files have changed
git status

# Outputs:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: README.md

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

another-file
my-new-file

# Using the flags -sb we can shorten the output
git status -sb

# Outputs:
## master
M README.md
?? another-file
?? my-new-file

Seluruh cerita


Ada kalanya terjadi kesalahan, misalnya, Anda secara tidak sengaja membuang perubahan bertahap (persiapan) sebelum melakukan perubahan. Jika git logtidak memungkinkan Anda untuk kembali ke keadaan sebelumnya dan tidak ada tips di atas yang membantu, itu adalah git reflog.

Semua tindakan Anda di Git yang mengubah isi tautan HEAD@{}(misalnya push/pull/branch/checkout/commit) termasuk dalam reflog (log referensi). Sebenarnya, ini adalah kisah dari semua tindakan Anda, tidak peduli di cabang mana Anda berada. Inilah perbedaan dengan git log, yang menunjukkan perubahan untuk cabang tertentu.


Anda dapat melakukannya git showdengan ID komit - dan melihat perubahan spesifik. Jika ini yang Anda cari, itu akan git checkoutmemindahkan Anda ke cabang yang diinginkan atau bahkan memungkinkan Anda memilih file tertentu, seperti yang ditunjukkan di atas:

# See the reference log of your activity
git reflog --all

# Look at the HEAD at given point from reflog
git show HEAD@{2}

# Checkout the HEAD, to get back to that point
git checkout HEAD@{2}

Siapkan file yang melewatkan komit


Dalam kasus ekstrem, jika git reflogtidak membantu mendapatkan file Anda kembali (misalnya, Anda menjalankan hard reset dengan file perantara), ada satu trik lagi.

Setiap perubahan disimpan di dalam objek .git/objectsyang diisi dengan file dalam proyek aktif, sehingga hampir mustahil untuk mengetahuinya. Namun, ada perintah Git yang disebut git fsck, yang digunakan untuk memeriksa integritas (keberadaan file yang rusak) di repositori. Kita dapat menggunakannya dengan bendera --lost-founduntuk mencari semua file yang tidak terkait dengan komit. File seperti itu disebut "dobel gumpalan".

Perintah ini juga memungkinkan Anda untuk menemukan "menggantung pohon" dan "menggantung komit." Jika mau, Anda bisa menggunakan flag --dangling, tetapi untungnya--lost-foundkarena mengekstrak semua file yang relevan ke dalam folder .git/lost-found. Kemungkinan besar, dalam proyek aktif Anda akan memiliki banyak file "menggantung" seperti itu. Git memiliki perintah pembuangan sampah yang berjalan secara teratur dan menghilangkannya.

Dengan demikian, ia --lost-foundakan menampilkan semua file dan waktu / tanggal pembuatan, yang sangat memudahkan pencarian. Perhatikan bahwa setiap file yang terpisah masih akan terpisah, yaitu, Anda tidak dapat menggunakan checkout. Selain itu, semua file akan memiliki nama yang tidak dapat dipahami (hash), jadi Anda harus menyalin file yang diperlukan ke lokasi lain:

# This will find any change that was staged but is not attached to the git tree
git fsck --lost-found

# See the dates of the files
ls -lah .git/lost-found/other/

# Copy the relevant files to where you want them, for example:
cp .git/lost-found/other/73f60804ac20d5e417783a324517eba600976d30 index.html

Git dalam kerja tim


Menggunakan Git sendiri adalah satu hal, tetapi ketika Anda bekerja dalam tim yang terdiri dari orang-orang, biasanya dengan pengalaman, keterampilan, dan alat yang sangat berbeda, Git dapat menjadi berkah atau kutukan. Ini adalah alat yang ampuh untuk berbagi basis kode yang sama, melakukan peninjauan kode dan memantau kemajuan seluruh tim. Pada saat yang sama, semua karyawan harus memiliki pemahaman yang sama tentang bagaimana menggunakannya dalam kerja tim. Terlepas dari apa itu: konvensi penamaan cabang, memformat pesan yang menyertainya dalam komit, atau memilih file mana yang akan dimasukkan dalam komit, penting untuk memastikan komunikasi yang baik dan sepakat tentang cara menggunakan alat ini.

Itu selalu penting untuk memastikan kesederhanaan orientasi untuk pemula dan untuk memikirkan apa yang akan terjadi jika mereka mulai membuat komitmen tanpa mengetahui prinsip dan konvensi yang diadopsi oleh perusahaan. Ini bukan akhir dari dunia, tetapi dapat menyebabkan kebingungan dan membutuhkan waktu untuk kembali ke pendekatan yang terkoordinasi.

Bagian ini berisi beberapa rekomendasi tentang bagaimana mengintegrasikan perjanjian yang diterima secara langsung ke dalam repositori itu sendiri, mengotomatisasi dan mengeluarkan jumlah tugas maksimum dalam deklarasi. Dalam kasus yang ideal, setiap karyawan baru segera mulai bekerja dengan gaya yang sama dengan anggota tim lainnya.

Akhiran baris yang sama


Secara default, Windows menggunakan ujung garis DOS \r\n(CRLF), sementara Mac dan Linux menggunakan ujung garis UNIX \n(LF), sedangkan versi Mac yang lebih lama menggunakan \r(CR). Dengan demikian, ketika tim tumbuh, masalah ujung garis yang tidak kompatibel menjadi lebih mungkin. Ini merepotkan, mereka (biasanya) tidak melanggar kode, tetapi karena itu, komitmen dan permintaan kumpulan menunjukkan berbagai perubahan yang tidak relevan. Seringkali orang mengabaikannya, karena cukup merepotkan untuk berjalan-jalan dan mengubah semua ujung jalur yang salah.

Ada solusinya - Anda dapat meminta semua anggota tim untuk mengonfigurasi konfigurasi lokal mereka untuk penyelesaian saluran otomatis:

# This will let you configure line-endings on an individual basis
git config core.eol lf
git config core.autocrlf input

Tentu saja, Anda perlu mendaftar untuk konvensi dan pemula ini, yang mudah untuk dilupakan. Bagaimana melakukan ini untuk seluruh tim? Menurut algoritme kerja, Git memeriksa keberadaan file konfigurasi di repositori .git / config, kemudian memeriksa konfigurasi pengguna di seluruh sistem ~/.gitconfig, dan kemudian memeriksa konfigurasi global di /etc/gitconfig.

Semua ini baik, tetapi ternyata tidak ada file konfigurasi ini yang dapat diinstal melalui repositori itu sendiri. Anda bisa menambahkan konfigurasi khusus repositori, tetapi mereka tidak akan meluas ke anggota tim lainnya.

Namun, ada file yang benar-benar berkomitmen untuk repositori. Ini disebut .gitattributes . Secara default, Anda tidak memilikinya, jadi buat file baru dan simpan sebagai*.gitattributes*. Ini menetapkan atribut untuk setiap file. Misalnya, Anda dapat memaksa git diff untuk menggunakan header exif dari file gambar alih-alih mencoba menghitung perbedaan dalam file biner. Dalam hal ini, kita bisa menggunakan wildcard sehingga pengaturan bekerja untuk semua file, bertindak, pada kenyataannya, sebagai file konfigurasi umum untuk seluruh perintah:

# Adding this to your .gitattributes file will make it so all files
# are checked in using UNIX line endings while letting anyone on the team
# edit files using their local operating system’s default line endings.
* text=auto

Sembunyi otomatis


Merupakan kebiasaan untuk menambahkan file yang dikompilasi (seperti node_modules/) ke .gitignore sehingga mereka disimpan secara lokal dan tidak diunggah ke repositori. Namun, terkadang Anda masih ingin mengunggah file, tetapi tidak ingin bertemu nanti setiap kali dalam permintaan kumpulan.

Dalam situasi ini (setidaknya di GitHub), Anda bisa menambahkan jalur bertanda ke .gitattributes linguist-generateddan memastikan bahwa .gitattributes ada di folder root repositori. Ini akan menyembunyikan file dalam permintaan kumpulan. Mereka akan "diperkecil": Anda masih dapat melihat fakta perubahan, tetapi tanpa kode lengkap.

Segala sesuatu yang mengurangi stres dan beban kognitif dalam proses peninjauan kode meningkatkan kualitasnya dan mengurangi waktu.

Misalnya, Anda ingin menambahkan file sumber daya (aset) ke repositori, tetapi Anda tidak akan memodifikasi dan melacaknya nanti, sehingga Anda bisa menambahkan baris berikut ke file dengan atribut:

*.asset linguist-generated

Gunakan kesalahan git lebih sering


Artikel Harry Roberts "Hal-Hal Kecil yang Saya Suka Lakukan Dengan Git" merekomendasikan git blame(menetapkan git praiseterjemahan ) untuk menetapkan alias (diterjemahkan dari terjemahan "Bahasa Inggris") untuk merasakan tim ini sebagai tindakan positif. Tentu saja, penggantian nama tidak mengubah perilaku tim. Tetapi setiap kali diskusi muncul dengan menggunakan fungsi git blame, semua orang menjadi tegang, dan tentu saja saya juga tegang. Wajar untuk menganggap kata menyalahkan (rasa bersalah) sebagai sesuatu yang negatif ... tetapi ini sepenuhnya salah!

Fungsi yang kuat git blame (atau git praise, jika Anda mau) menunjukkan siapa yang terakhir bekerja dengan kode ini. Kami tidak akan menyalahkan atau memuji dia, tetapi hanya ingin memperjelas situasinya. Menjadi lebih jelas pertanyaan mana yang harus ditanyakan dan kepada siapa, yang menghemat waktu.

Itu harus disajikan git blametidak hanya sebagai sesuatu yang baik, tetapi juga sebagai alat komunikasi yang membantu seluruh tim untuk mengurangi kekacauan dan tidak membuang waktu mencari tahu siapa yang tahu apa. Beberapa IDE, seperti Visual Studio, mengaktifkan fitur ini sebagai anotasi. Untuk setiap fungsi, Anda langsung melihat siapa yang terakhir mengubahnya (dan, karenanya, dengan siapa harus dibicarakan).

Analog git menyalahkan file yang hilang


Baru-baru ini, saya melihat seorang pengembang di tim kami mencoba mencari tahu siapa yang menghapus file, kapan, dan mengapa. Sepertinya itu bisa membantu di sini git blame, tetapi berfungsi dengan garis-garis dalam file dan tidak berguna jika file tersebut hilang.

Namun, ada solusi lain. Setia tua git log. Jika Anda melihat log tanpa argumen, Anda akan melihat daftar panjang semua perubahan di cabang saat ini. Anda dapat menambahkan pengidentifikasi komit untuk melihat log komit khusus ini, tetapi jika Anda menentukan --(yang kami gunakan sebelumnya untuk menargetkan file tertentu), Anda bisa mendapatkan log untuk file - bahkan yang tidak lagi ada:

# By using -- for a specific file,
# git log can find logs for files that were deleted in past commits
git log -- missing_file.txt

Templat Pesan Komit


Pesan komit seringkali perlu ditingkatkan. Cepat atau lambat, para pengembang dalam tim sampai pada kesimpulan ini. Ada banyak cara untuk meningkatkan. Misalnya, Anda dapat merujuk ke pengidentifikasi bug dari alat manajemen proyek internal, atau mungkin mendorong untuk menulis setidaknya beberapa teks daripada pesan kosong.

Perintah ini perlu dijalankan secara manual setiap kali seseorang mengkloning repositori, karena file konfigurasi tidak dikomit ke repositori. Namun, itu nyaman karena Anda dapat membuat file umum dengan nama apa pun yang bertindak sebagai templat pesan komit:

# This sets the commit template to the file given,
# this needs to be run for each contributor to the repository.
git config commit.template ./template-file

Git untuk otomatisasi


Git adalah alat otomatisasi yang kuat. Ini tidak segera jelas, tetapi pikirkan sendiri: dia melihat semua aktivitas Anda di repositori - plus aktivitas peserta lain - dan dia memiliki banyak informasi yang bisa sangat berguna.

Git hooks


Cukup sering, Anda melihat bahwa anggota tim melakukan tugas yang berulang saat bekerja. Ini bisa menjadi tes untuk lulus tes dan linter sebelum mengirim cabang ke server (kait sebelum mengirim) atau strategi paksa untuk penamaan cabang (kait sebelum melakukan). Mengenai hal ini, Konstantinos Lamonis menulis sebuah artikel di Smashing Magazine yang berjudul “Cara Menyederhanakan Alur Kerja Menggunakan Git Hooks” .

Otomatisasi manual


Salah satu fitur otomatisasi utama dalam Git adalah git bisect. Banyak yang telah mendengarnya, tetapi sedikit yang menggunakannya. Intinya sedang memproses pohon Git (komit sejarah) dan menemukan di mana kesalahan dimasukkan.

Cara termudah untuk melakukannya adalah dengan tangan. Anda mulai git bisect start, atur pengidentifikasi dari komitmen baik dan buruk (di mana tidak ada bug dan di mana ada bug), kemudian jalankan git bisect goodatau git bisect baduntuk setiap komit.

Ini adalah fitur yang lebih kuat daripada yang terlihat pada pandangan pertama, karena tidak menjalankan Git log secara linear, yang dapat dilakukan secara manual sebagai proses berulang. Sebagai gantinya, ia menggunakan pencarian biner yang secara efektif melewati komit dengan jumlah langkah paling sedikit:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Here, do your test for the bug.
# This could be running a script, doing a journey on a website, unit test etc.

# If the current commit has bug:
git bisect bad

# If the current commit does not have the bug
git bisect good

# This will repeat until it finds the first commit with the bug
# To exit the bisect, either:

# Go back to original branch:
git bisect reset

# Or stick with current HEAD
git bisect reset HEAD

# Or you can exit the bisect at a specific commit
git bisect reset <commit ID>

Pindah: Otomasi Ilmiah


Dalam laporan debugging ilmiahnya, Stuart Halloway menjelaskan cara menggunakan perintah git bisectuntuk mengotomatiskan debugging.
Dia fokus pada Clojure, tetapi kita tidak perlu tahu bahasa ini untuk mendapat manfaat dari ceramahnya.

Git bisect adalah otomatisasi ilmiah. Anda menulis sebuah program kecil yang akan menguji sesuatu, dan Git melompat bolak-balik, memotong dunia menjadi dua dengan setiap lompatan, sampai menemukan batas di mana tes Anda berubah.
Stuart Halloway

Pada awalnya git bisectmungkin tampak seperti fitur yang menarik dan cukup keren, tetapi pada akhirnya itu tidak terlalu berguna. Kinerja Stewart sebagian besar menunjukkan bahwa sebenarnya kontraproduktif untuk melakukan debug seperti yang biasa kita lakukan. Jika Anda sebaliknya berfokus pada fakta empiris, apakah tes tersebut lulus atau tidak, maka Anda dapat menjalankannya pada semua komitmen, mulai dengan versi yang berfungsi, dan mengurangi perasaan "berkeliaran dalam gelap" yang biasa kita alami.

Jadi bagaimana kita mengotomatisasigit bisect? Anda bisa memberikannya skrip untuk setiap komit terkait. Sebelumnya, saya mengatakan bahwa Anda dapat menjalankan skrip secara manual pada setiap langkah membagi dua, tetapi jika Anda melewati perintah untuk menjalankan, skrip ini akan secara otomatis menjalankan skrip pada setiap langkah. Ini bisa berupa skrip khusus untuk debugging masalah khusus ini atau tes (modular, fungsional, integrasi, semua jenis tes). Dengan demikian, Anda dapat menulis tes untuk memverifikasi bahwa regresi tidak berulang, dan menjalankan tes ini pada komitmen sebelumnya:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Tell git to run a specific script on each commit
# For example you could run a specific script:
git bisect run ./test-bug

# Or use a test runner
git bisect run jest

Di setiap komitmen masa lalu


Salah satu kelebihannya git bisectadalah penggunaan efektif pencarian biner untuk mem-bypass semua peristiwa dalam sejarah dengan cara non-linear. Tetapi kadang-kadang diperlukan bypass linier. Anda dapat menulis skrip yang membaca log Git dan memutari kode pada setiap komit. Tapi ada seorang teman, yang akan melakukannya untuk Anda: git rebase.

Kamran Ahmed dalam sebuah tweet yang ditulis rebaseapa adanya, apa yang dilakukan komit tidak lulus ujian:

Temukan komit yang gagal dalam tes:

$ git rebase -i --exec "yarn test" d294ae9

Perintah menjalankan pengujian benang pada semua komit antara d294ae9 dan HEAD dan berhenti di komit ketika tes mogok.

Kami telah mempertimbangkan git bisectuntuk tugas ini, yang mungkin lebih efisien, tetapi dalam hal ini kami tidak terbatas pada satu kasus penggunaan.

Ada tempat untuk kreativitas. Mungkin Anda ingin membuat laporan tentang bagaimana kode telah berubah dari waktu ke waktu (atau menunjukkan riwayat pengujian), dan hanya menguraikan log Git tidak cukup. Mungkin ini bukan trik yang paling berguna dalam artikel ini, tetapi menarik dan menunjukkan tugas, kenyataan yang sebelumnya tidak bisa kita percayai:

# This will run for every commit between current and the given commit ID
git rebase -i --exec ./my-script

Pilihan artikel dan manual untuk membantu Anda masuk lebih dalam ke Git


Dalam artikel seperti itu, tidak mungkin untuk mempelajari topik, jika tidak, Anda akan mendapatkan seluruh buku. Saya memilih beberapa trik kecil yang bahkan mungkin tidak diketahui oleh pengguna berpengalaman. Tetapi Git memiliki lebih banyak fitur: dari fungsi dasar hingga skrip yang rumit, konfigurasi yang tepat, dan integrasi konsol. Karena itu, berikut adalah beberapa sumber yang mungkin menarik bagi Anda:

  1. Explorer git . Situs interaktif yang membantu Anda dengan mudah memahami bagaimana mencapai apa yang Anda inginkan.
  2. Sial, git! . Kita masing-masing di beberapa titik dapat tersesat di Git dan tidak tahu bagaimana menyelesaikan masalah apa pun. Situs ini menyediakan solusi untuk banyak masalah yang paling umum.
  3. Pro git . Buku gratis ini adalah sumber yang sangat berharga untuk memahami Git.
  4. Git Docs. — . , Git Docs, Git (, man git-commit) Git .
  5. Thoughtbot. Git Thoughtbot .
  6. Git. Git.
  7. Git. , … . Git, .
  8. Git: dari tingkat pemula hingga mahir . Mike Ritmüller telah menulis artikel bermanfaat ini, yang sangat ideal untuk pengguna pemula Git.
  9. Hal-hal kecil yang saya suka lakukan dengan Git . Artikel dari Harry Roberts inilah yang membuat saya menyadari betapa banyak kemungkinan yang masih mengintai di Git, selain dari memindahkan kode melintasi cabang.
  10. Panduan Git Lanjutan Atlassian . Tutorial ini merinci banyak topik yang disebutkan dalam artikel ini.
  11. Git cheat sheet di Github . Selalu nyaman untuk memiliki lembar contekan yang bagus untuk alat seperti Git.
  12. Pengurangan git . Artikel ini merinci berbagai flag perintah Git dan merekomendasikan banyak alias.

Tapi apa lagi yang bisa Anda baca :

  1. Git. №1: , .git
  2. Git. №2: rebase.
  3. .

All Articles