Git Repository İşlemleri ve Komutlar
Git ve ardından öne çıkan git platformları ile git kullanım sürecine geçtik.
Bu yazıda, öncelikle örnek iki durum üzerinden işlemler gerçekleştireceğiz. Ardından, örnek işlemlerde yer alan komutların detaylarına değinmeye çalışacağım. İlk örneğimiz bir projeyi nasıl git directory’e aktaracağımız üzerine olacak, bir diğer örnekte de git directory’deki (repository) bir projeyi bilgisayarımıza nasıl indirebileceğimize bakacağız.
Git Konfigürasyonu
Öncelikle, bu örnek işlemler ve komut uygulamaları için sistemimizde git‘in kurulu olduğunu varsayıyorum. Dolayısıyla, bir sonraki adımımız konfigürasyon düzenlemesi olacak. Öncelikle halihazırda bir tanımlama olup olmadığını kontrol edelim.
git config --list
Komutu uyguladığımızda eğer bir tanımlama yapılmamışsa boş bir geri dönüş alırız. O halde kullanıcı tanımımızı yapalım.
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
Şimdi git config --list
kodunu uyguladığımızda user.name
ve user.email
tanımlarını alırız. Bu tanımlama ~/.gitconfig
içerisinde yer almaktadır. cat ~/.gitconfig
komutu ile dosya içeriğine göz atabilirsiniz.
Bir Git Yazılım Havuzu (Repository) Oluşturmak
Projemiz için newproject
adında bir klasör oluşturarak başlayalım.
mkdir newproject
cd newproject
Proje içeriğimiz şu şekilde olabilir.
.
├── dist
│ ├── bundle.js
│ ├── css
│ ├── img
│ ├── js
│ └── view
├── package-lock.json
├── package.json
├── src
│ ├── css
│ ├── img
│ ├── index.js
│ ├── js
│ │ ├── bar.js
│ │ └── foo.js
│ └── layout
├── webpack.config.js
└── yarn.lock
10 directories, 8 files
Şimdi, klasörü git’e işlemek için git init
kullanmamız gerekir. init
boş bir Git repo’su oluşturur (initialize) veya mevcut olanı yeniden yapılandırır (reinitialize). Komutun uygulanmasının ardından gerekli yazılım havuzu dosyalarını içeren .git
adında bir alt klasör oluşturulur.
git init
Ancak, bu aşamada projedeki hiçbir şey sürüm kontrolüne girmiş değildir. Detaylar için git-init1 kaynakçasına göz atabilirsiniz. Artık var olan dosyalarınızı sürüm kontrolüne alabiliriz. Bu işlem sürüm kontrolüne almak istediğimiz dosyaları belirleyip kayıt altına aldığınız birkaç git komutuyla gerçekleştirilebilir.
Tüm dosyaları işleme almak için git add .
komutunu kullanabiliriz. Ancak, node_modules
gibi bir klasörü işleme almak istemeyebiliriz. Neticede, repo’yu indiren bir kullanıcı yarn veya npm ile package.json içeriğini işleme alabilir. Bu durumda dosya isimlerini spesifik olarak işleme almamız veya .gitignore
dosyası oluşturup işleme alınmasını istemediğimiz dosyaları tanımlamamız daha uygun olacaktır.
Adım adım bu konulara değinelim. İlk olarak src
klasörünün içeriğini ve ardından webpack.config.js
dosyasını ele alalım.
git add src/* webpack.config.js
Bu yöntemin, düzenleme yapılan temel bazı dosyaları işleme almak için oldukça pratik olsa da birden fazla dosya ve klasörle çalıştığımızda biraz can sıkıcı olabilmekte. Yukarıdaki komut yerine şu şekilde de bir yol izleyebiliriz.
git add -u
git reset -- src/index.js node_modules
Bu durumda özellikle belirttiğimiz dosya ve klasörler dışındaki tüm içeriğimiz index‘e eklenecektir.
.gitignore
ise git add .
gibi genel ifadelerde görmezden gelinmesini istediğimiz dosyaları tanımlamamızı sağlayan bir konfigürasyon dosyasıdır ve bizi tek tek işlemler yapma zorunluluğunda kurtarır. Örnek olarak, node_modules
için bir .gitignore dosyası oluşturalım.
touch .gitignore
echo node_modules/ >> .gitignore
Bu işlemin ardından git add .
komutunu kullandığımızda .gitignore
içeriğine bakılır ve burada belirtilen dosya veya dizinler işlem dışında tutulur. github/gitignore altında oluşturulmuş pek çok .gitignore
örneğini görüntüleyebilirsiniz.
Geldik bir sonraki adıma. Artık dosyalarımızı kayıt altına alabiliriz.
git commit
Bu komutu uyguladığımızda bir commit mesajının da iletilmesinin hoş olacağı uyarısını alırız.
git commit -m 'projenin ilk hali'
Elbette mesaj tanımı bir zorunluluk değil, ancak projenin geliştirilmesi sürecinde yapılan değişikliklere dair bir açıklama düşmek faydalı olacaktır.
git commit -a --allow-empty-message -m ''
Yukarıdaki komut ile commit
işlemini mesaj tanımlamadan (boş mesaj ile) gerçekleştirebiliriz. Her defasında bu tanımı yapmak istemiyorsak, ilgili tanımı --global
ile config
‘e alias.nccommit
olarak işleyebiliriz.
git config --global alias.nccommit 'm-message -commit -a --allow-empty ""'
İşlemlerimiz bu kadar!
Bir Yazılım Havuzunu (Repository) Klonlamak
Bir projemizi nasıl yazılım havuzu olarak kayıt edebileceğimizi öğrendiğimize göre, bir sonraki aşamada var olan bir repository’i -örneğin, projeye katkıda bulunmak amacıyla- nasıl edinebileceğimize (klonlamak) bakabiliriz. Bu amaçla kullanacağımız komut git clone
. Diğer versiyon kontrol sistemlerine aşina iseniz checkout
yerine neden clone
kullanıldığını merak ediyor olabilirsiniz. Git SCM yazısında da belirttiğim üzere, Git sunucuda bulunan her dosyanın proje tarihçesinde bulunan her sürümü de dahil neredeyse tüm veriyi kopyalar. Bu nedenle clone
komutu kullanılmaktadır. Hatta, bu sayede sunucuda bir sorun yaşanması durumunda (dosya silme, donanım hatası, erişim kısıtlaması vb.) klonlanan herhangi bir kayıt üzerinden sunucudaki zamana geri dönülebilir.
git clone
repo URL‘i birlikte kullanılır.
git clone [repository-url]
Örneğin, GitLab‘de barındırdığım webpack-test isimli repo’yu indirelim. Bu işlemi 3 şekilde gerçekleştirebiliriz.
# git
git clone git://gitlab.com/ceaksan/webpack-test.git
# https
git clone https://gitlab.com/ceaksan/webpack-test.git
# ssh
git clone git@gitlab.com:ceaksan/webpack-test.git
SSH bağlantısı için bağlantı gerçekleştireceğiniz sunucunun key’inizi tanıyor olması gerekmektedir. Diğer seçenekler için ekstra bir ayar ya da gereksinim söz konusu değildir.
Yukarıdaki komutlardan uygun olanın kullanılmasının ardından proje adıyla (webpack-test) bir klasör oluşturulur. Ardından, .git
alt dizini oluşturulur. Repo’ya ait tüm verinin indirilmesinin ardından son sürümün bir kopyası seçilir (checkout) ve üzerine çalışılabilir olarak sunulur. İndirme işlemini elbette proje adıyla gerçekleştirmek zorunda değiliz. Farklı bir isimle (örneğin, newproject) projeyi yapılandırmak istersek şu komut işimizi görecektir.
git clone git://gitlab.com/ceaksan/webpack-test.git newproject
Artık üzerinde çalışılabilir dosyaları edindiğimize göre git show
ile hızlı bir kontrol işlemi gerçekleştirebiliriz. Bu komut ile projeye / repoya dair tüm detayları görüntüleyebiliriz. Bu aşamada edindiğimiz tüm dosyalar izlenen (tracked) ve değişmemiş dosyalardır.
Değişikliklerin İşlenmesi
Bundan sonraki süreçte, dosyalar üzerinde çalışmaya başladığımızda unutmamamız gereken konu, klasörümüzdeki dosyaların iki halden birinde bulunacağıdır; izlenenler (tracked) ve izlenmeyenler (untracked).
İzlenen dosyalar, bir önceki bellek kopyasında bulunan dosyalardır. Bu dosyalar değişmemiş, değişmiş ya da hazırlanmış olabilirler. Bu dosyaların haricindeki her şey —çalışma klasörünüzde olup bir önceki bellek kopyasında ya da hazırlama alanında bulunmayanlar— izlenmeyen dosyalardır.
Bir dosyaya müdahale ettiğimizde artık o dosya git için değişmiş olarak nitelendirilir. Bu aşamadan sonra, değişikliğe uğrayan dosyaları önce hazırlayıp sonra bütün hazırlanmış değişiklikleri kaydetmeliyiz. Bu süreç çalışma sürecinin tamamında döngüsel olarak tekrarlanır.
Dosyaların Durumlarının Kontrol Edilmesi
Hangi dosyanın hangi konumda bulunduğunu git status
komutu ile görüntüleriz. Örnek olarak src/templates/index.html
dosyasında bir işlem gerçekleştirdim ve git status
komutunu çalıştırdım. Aldığım karşılık şu oldu:
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: src/templates/index.html
no changes added to commit (use "git add" and/or "git commit -a")
Eğer herhangi bir değişiklik söz konusu olmasaydı nothing to commit, working directory clean
mesajı dönecekti.
Ek olarak, dizin içerisinde bir README dosyası olmadığını gördüm. O halde proje ile ilgili bazı detayların yer alacağı bir README
dosyası oluşturalım ve ardından yine git status
ile durum kontrolü gerçekleştirelim.
touch README
echo '# It is a New Project' >> README
Bu işlemin ardından git status bana şu dönüşü sağlar.
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: src/templates/index.html
Untracked files:
(use "git add ..." to include in what will be committed)
README
no changes added to commit (use "git add" and/or "git commit -a")
İletilen açıklamalardan da anlaşıldığı üzere src/templates/index.html
modified, README ise untracked olarak nitelendirilmekte. O halde README
dosyasını da git add README
ile bir üst aşamaya geçirmem gerekiyor. Ardından, git status
komutunu tekrar uyguladığımda README
dosyası new file
olarak nitelendirilecek ve izlenmeye başlanacaktır. README
dosyasını açıp bir düzenleme yaptığınızda artık dosyanın modified olarak belirtildiğini görebilirsiniz.
Peki, dosyalardaki bu değişiklikleri görüntülemek istersek diff
komutunu kullanabiliriz.
git diff
Komutun uygulanmasının ardından dosyalardaki değişiklikler bize ön tanımlı metin editörü üzerinden satır numaralarıyla birlikte sunulur. Unutmadan ekleyeyim, git diff
bize son kayıttan beri yapılan bütün değişiklikler yerine sadece kayda hazırlanmamış değişiklikleri gösterir. Eğer sadece kayda hazırladığımız değişiklikleri görüntülemek istersek git diff --cached
komutunu kullanmamız gerekir.
Artık yaptığımız değişikliklerin kayıt edilmesini (commit) sağlayabiliriz.
git commit -m "New comment"
Komutun uygulanmasının ardından, yaptığımız işlemleri özetleyen şu dönüşü alırız.
[master aa88c360] New comment
1 file changed, 1 insertion(+)
create mode 100644 README
Hazırlık alanını atlamak istersek git commit -a -m ''
ile işlemimizi sürdürebiliriz.
Peki, bir dosyayı silmek / taşımak istediğimizde ne yapmalıyız? Bu gibi durumlarda rm
(silme) ve mv
(taşıma veya isim değiştirme) komutlarını kullanmamız işlemlerin daha kolay takip edilmesini sağlayacaktır. Doğrudan klasör içerisinde gerçekleştireceğimiz işlemler sonucunda sorun yaşamak istemiyorsak rm
kullanımını bir alışkanlık haline getirmemiz uygun olacaktır. Örnek olarak README dosyasını silelim.
git rm README
Komutun uygulanmasının ardından, README dosyası bir sonraki kayıtta artık izlenmeyecektir. Ancak, bazı durumlarda dosyayı değiştirmiş ve çoktan indekse eklemiş olabiliyoruz. Bu gibi durumlarda ortadan kaldırma işlemini -f
seçeneğini kullanarak zorlamamız gerekir. Diğer yandan, bir dosyayı çalışma klasörünüzde tutup, kayda hazırlık alanından silmek de isteyebiliriz. Bu durumda git rm --cached [dosya-adi]
komutundan faydalanabiliriz. Taşıma işlemleri veya dosya ismi değişikliklerinde de benzer kurallar söz konusudur. Değişen tek şey rm
yerine mv
komutundan faydalanacak olmamızdır.
git mv README readme.txt
Komutun uygulanmasının ardınan readme.txt
dosyası renamed olarak nitelendirilecektir.
mv
komutu yerine şu şekilde de ilerleyebilirdik.
git rm README.txt
git add README
Tüm bu değişikliklerin ardından yine işlemleri commit
ile kayıt altına almamız gerekir. Peki, ya gerçekleştirilen bir kaydı geri almak istersek? Bu gibi durumlarda (örneğin bir dosyayı kayda işlememişsek) --amend
seçeneğini kullanırız.
git commit --amend
Bu komutu uyguladığımızda hazırlık alanındaki değişiklikler alınır ve kaydı değiştirmek için kullanılır.
Kayda alınmış bir dosyayı hazırlık alanından kaldırmak istediğimizde ise git reset
komutunu kullanırız. Bu komutu yazının ilk bölümünde src/index.js
ve node_modules
gibi dosya ve klasörlerin kayıt altına alınmasını engellemek için kullanmıştık. Şimdide bu işlemi readme.txt
için gerçekleştirelim.
git reset HEAD readme.txt
Son olarak, değişmiş bir durumdaki bir dosyayı değişmemiş duruma nasıl getirebileceğimize bakalım. Örneğin, bir dosyada çeşitli düzenlemeler yaptınız ve kayıt altına alacaksınız. git status
ile durum kontrolü yaptığınızda işlem yaptığınız dosyanın haricinde de düzenlenmiş dosyaların beklediğini gördünüz. Ancak, yapılan değişikliklerden emin değilsiniz. diff
ile değişiklikleri görüntülediniz ve değişikliklerin geri alınmasına karar verdiniz. Bu gibi durumlarda kullanacağımız komutumuz git checkout -- [dosya-adi]
olacaktır.
git checkout -- readme.txt
Şimdi bir sonraki başlığımıza geçebiliriz. Bilgisayarımızda yeni oluşturduğumuz ve/veya klonladığımız bir projeyi nasıl uzak uçbirime (GitHub, GitLab vb.) ileteceğiz?
Uzaktaki Repository’lerle Çalışmak
Uzaktaki yazılım havuzları (repository), projenizin İnternet’te ya da başka bir ağda barındırılan sürümleridir. Bu projeler ya salt okunur ya da okunur/yazılır durumdadır. Ortak çalıştığımız okunur/yazılır durumdaki projelerde değişiklik yapabilir, veri çekip (pull) onlara veri itebiliriz (push). Yukarıdaki örnekte GitLab’de barındırdığım webpack-test çalışmasını kullanmıştık. Yine bu çalışma üzerinden devam edelim. Ön bilgi olarak, çalışmanın iki adet dalı (branch) var; master ve cea. Master ön tanımlı dalın adıdır ve değiştirilmediği / silinmediği sürece bu ad ile erişilebilir. Genellikle master branch üzerinden pek işlem gerçekleştirilmez ve yeni bir branch ile işlemler yürütülür.
O halde, ilk olarak indirdiğimiz webpack-test
(eğer isim değiştirmediysek) çalışmasının hangi uzak sunucularla ilişkilendirildiğine bakalım.
git remote
Komutun uygulanmasının ardından origin
dönüşünü alırız; origin
bir uzak uçbirimin belirlenmiş kısa adıdır. -v
seçeneği ile origin
olarak ifade edilen uzak uçbirimin URL‘ini de görüntüleyebiliriz.
git remote -v
Bu durumda şu dönüşü alırız.
origin git@gitlab.com:ceaksan/webpack-test.git (fetch)
origin git@gitlab.com:ceaksan/webpack-test.git (push)
Elbette projede birden fazla uçbirim olabilir. Yani, farklı kullanıcılar proje üzerine çalışıyor olabilir. Bu durumda yukarıdaki dönüş diğer uçbirimleri de içerecektir. Ek olarak, bizde bu kullanıcıların herhangi birinden kolaylıkla çekme işlemi (pull) yapabiliriz.
Uzaktaki bir repositery’i git remote add [kisa-ad] [repositery-url]
ile farklı bir isimle de ekleyebiliriz.
git remote add ceaksan https://gitlab.com/ceaksan/webpack-test.git
Bu durumda, git remote -v
komutunu kullandığımızda şu dönüş alınır.
wt https://gitlab.com/ceaksan/webpack-test.git (fetch)
wt https://gitlab.com/ceaksan/webpack-test.git (push)
origin git@gitlab.com:ceaksan/webpack-test.git (fetch)
origin git@gitlab.com:ceaksan/webpack-test.git (push)
Fark ettiyseniz uçbirimler remote
işleminde kullandığımız protokoller (https, ssl, git) ile listelenmekte.
Yukarıdaki isimlendirmenin ardından artık komutlarda belirttiğimiz ismi (örnekte wt) kullanmaya başlayabiliriz. O halde, git fetch wt
ile yazılım havuzunda bulunan ancak bizde bulunmayan bütün bilgileri (yeni dal vb.) edinebiliriz.
From https://gitlab.com/ceaksan/webpack-test
* [new branch] cea -> wt/cea
* [new branch] master -> wt/master
Görüldüğü üzere yeni branch ve remote bağlantı bilgileri bize iletildi. Bu bilgiler ışığında, cea
dalına wt/cea
ile erişebileceğimi, bu dal ile birleştirme (merge) işlemi yapabileceğimi ve bu dallardan birini yeral dal olarak seçip içeriğine erişebileceğimi gördüm.
git fetch wt
ile tüm bilgileri edinmenin yanı sıra, projede uzak repository’deki bütün dallara da referans oluşur. Bu sayede kolaylıkla proje içeriğini inceleyebilir ve/veya merge işlemi gerçekleştirebiliriz. Tekrar belirtmekte fayda var; fetch
sadece bilgi getirir herhangi bir merge (birleştirme) işlemi gerçekleştirilmez. Bu işlem ayrıca uygulanır. Şayet, uzaktaki bir dalı izlemek üzere ayarladığımız bir dalımız varsa git pull
ile tek seferde bu dalın ilişkili olduğu uzak daldan güncel veriyi edinebilir ve değişiklikleri mevcut dalımızla birleştirebiliriz.
Artık projemiz paylaşıma hazır. Paylaşma işlemi için yaptığımız değişiklikleri git push [uzak-sunucu-adi] [dal-adi]
ile uzak uçbirime push etmeliyiz. Push işlemini farklı uçbirim adları üzerinden gerçekleştirebiliriz.
# origin için
git push origin master
# wt için
git push wt master
Klonlama (git clone) aşamasında genellikle isimlendirmeler ön tanımlı oldukları şekilde ele alınır. Belirli bir uzak uçbirim ile ilgili bilgi almak için git remote show [ucbirim-adi]
komutunu kullanabiliriz.
git remote show wt
Yukarıdaki komutu uyguladığımızda şu dönüşü alırız.
* remote wt
Fetch URL: https://gitlab.com/ceaksan/webpack-test.git
Push URL: https://gitlab.com/ceaksan/webpack-test.git
HEAD branch: master
Remote branches:
cea tracked
master tracked
Local ref configured for 'git push':
master pushes to master (up to date)
Yeni bir proje olarak (uzak uçbirim’de henüz böyle bir proje yok ise) tanımlamak için:
git push -u https://[uzak-ucbirim]/[yeni-proje-adi].git master
Son olarak, bir uzak uç birimin adını git remote rename [ucbirim-adi]
ile değiştirebilir, bir uçbirimi git remote remove [ucbirim-adi]
veya git remote rm [ucbirim-adi]
ile silebiliriz.
Son Olarak
Şimdilik git işlemleri ve bu işlemler içerisinde kullanacağımız komutlara dair anlatacaklarım bu kadar. Etiketleme, dallar ve komutlarla ilgili detaylara örnek durumlar üzerinden değinmenin daha doğru ve anlaşılır olacağını düşünüyorum. Ancak, öncesinde ilgili konulara dair detaylı anlatımlara ulaşmak isterseniz aşağıdaki ileri okumalar ve kaynakça bölümlerine göz atabilirsiniz.