git push: değişiklikleri uzak depoya nasıl gönderirsiniz
git push, mevcut branch'inizdeki sunucuda olmayan commit'leri uzak depoya (genellikle origin) gönderir ve oradaki branch işaretçisini ilerletir. Branch'i ilk kez git push -u origin branch-adi ile yayımlayın; sonrasında git push yeterlidir. Sunucuda başkalarının commit'leri varsa önce git pull ile alın; force push ile üzerine yazmayın.
git push ne yapar
git push, yerel branch'inizdeki ve sunucuda henüz bulunmayan commit'leri uzak depoya (genellikle adı origin olan) iletir ve oradaki branch işaretçisini son commit'inize taşır. Çalışma dizinindeki dosyalar ve commit edilmemiş değişiklikler oraya gitmez: yalnızca geçmiş, yani commit'ler gönderilir.
Push bir «senkronizasyon» değildir. Tek yönlü çalışır: yerelden uzağa. Başkalarının değişikliklerini almak için git fetch ya da git pull gerekir. Bu yönleri karıştırmak, yeni başlayanların mentora sorduğu sorunların neredeyse tamamının kaynağıdır.
Git'in bir kuralı daha var: push varsayılan olarak yalnızca «ileri sarma» (fast-forward) olarak kabul edilir. Sunucu, commit'lerinizi mevcut geçmişin devamıysa kabul eder. Biri sizden önce kendi commit'lerini göndermişse push reddedilir — bu bir hata değil, korumadır.
Komutun sözdizimi
git push [<remote>] [<yerel-branch>[:<uzak-branch>]]
Parametre vermeden git push çalıştırırsanız Git mevcut branch'i, upstream (izlenen) olarak ayarlanmış branch'e gönderir. Açık biçim, upstream henüz ayarlanmamışsa ya da branch'i sunucuda farklı bir adla göndermek istiyorsanız işe yarar:
git push origin main # yerel main'i origin/main'e gönder
git push origin feature/login # feature/login branch'ini gönder
git push origin fix:hotfix-123 # yerel fix'i sunucuda hotfix-123 olarak gönder
git push origin HEAD # mevcut branch'i aynı adla gönder
Değişiklikleri ilk kez gönderme
Yeni bir projeden GitHub ya da GitLab'deki koda giden tipik yol şöyledir. Önce sunucuda boş bir depo oluşturursunuz, sonra yerel depoyu buna bağlayıp branch'i gönderirsiniz.
git init
git add .
git commit -m "İlk commit"
git branch -M main
git remote add origin git@github.com:user/project.git
git push -u origin main
-u bayrağı (tam hâli --set-upstream) yerel main branch'ini uzak origin/main ile ilişkilendirir. Bundan sonra bu branch'te yalnızca git push ve git pull yazmanız yeterlidir; git status de sunucunun kaç commit önünde ya da gerisinde olduğunuzu göstermeye başlar.
Remote'un hangi adrese baktığını git remote -v ile görebilirsiniz. Adres yanlışsa depoyu silip yeniden oluşturmak yerine git remote set-url origin <yeni-adres> ile düzeltin.
Yeni bir branch'i gönderme
Bir görev için branch oluşturdunuz, commit'lerinizi yaptınız ve git push yazdınız. Git şu yanıtı verir:
fatal: The current branch feature/login has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin feature/login
Bu bir hata değil, bir ipucudur: branch'in sunucuda henüz bir karşılığı yok. Önerilen komutu çalıştırın ya da kısa biçimi kullanın: git push -u origin feature/login. Tüm yeni branch'ler için bunu otomatik yapmasını istiyorsanız ayarı açın (Git 2.37 ile birlikte gelir):
git config --global push.autoSetupRemote true
git push neden reddedildi: rejected, non-fast-forward
Ekip çalışmasında en sık karşılaşılan durum:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'github.com:user/project.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.
Bir meslektaşınız commit'lerini sizden önce gönderdi. Sizin geçmişiniz ile sunucudaki geçmiş ayrıldı ve Git push'u kabul etseydi meslektaşınızın commit'leri kaybolurdu. Doğru çözüm, önce değişiklikleri alıp kendi commit'lerinizi bunların üzerine yerleştirmektir:
git pull --rebase # başkalarının commit'lerini al, kendininkileri üstüne yerleştir
# çakışma varsa: dosyaları düzelt, git add, git rebase --continue
git push
--rebase yerine düz git pull de yapabilirsiniz; bu durumda bir birleştirme commit'i oluşur. İkisi de doğrudur; çoğu ekipte kendi yerel commit'leriniz için geçmişin doğrusal kalması adına rebase tercih edilir. Önemli olan, reddi --force ile aşmamaktır.
git push --force ve --force-with-lease
Zorla gönderme, branch'in geçmişini bilinçli olarak yeniden yazdığınızda gerekir: git commit --amend, git rebase ya da inceleme öncesinde commit'leri birleştirdiyseniz. Sıradan push böyle bir branch'i kabul etmez, çünkü sunucudaki eski commit'ler artık yeni commit'lerin atası değildir.
git push --force-with-lease
--force-with-lease, sunucudaki branch yerel Git'in son gördüğü yerde (origin/<branch> işaretinde) duruyorsa üzerine yazar. Bir meslektaşınız bu arada bir şey göndermişse komut reddeder ve onun işini silmezsiniz. Düz --force (-f) bu kontrolü yapmaz ve her şeyin üzerine sessizce yazar.
Bir incelik var: bundan hemen önce git fetch çalıştırırsanız origin/<branch> işareti güncellenir ve koruma işlevini yitirir — Git, sanki siz başkasının commit'lerini «görmüşsünüz» gibi davranır. Bu yüzden, ne geldiğine bakmadan force push'tan önce fetch yapmayın.
| Komut | Ne yapar | Ne zaman kullanılır |
|---|---|---|
git push | Yalnızca fast-forward | Her zaman varsayılan olarak |
git push --force-with-lease | Kontrollü üzerine yazma | Rebase ya da amend sonrası kendi branch'iniz |
git push --force | Kontrolsüz üzerine yazma | Neredeyse hiçbir zaman; asla ortak branch'lere |
Ortak branch'lere (main, develop) zorla push yapılamaz: eski geçmişi çekmiş herkesin kopyası sunucudakinden ayrılır. Bu branch'ler genellikle depo ayarlarıyla da korunur ve sunucu protected branch hook declined yanıtı verir.
Etiketleri (tag) gönderme
Sıradan git push etiketleri göndermez. Bunları açıkça belirtmeniz gerekir:
git tag -a v1.2.0 -m "Sürüm 1.2.0"
git push origin v1.2.0 # tek bir etiket
git push --tags # yerel tüm etiketler
git push --follow-tags # commit'ler ve bunlara işaret eden açıklamalı etiketler
--follow-tags, --tags'ten daha kullanışlıdır: rastgele yerel hafif etiketleri göndermez; yalnızca açıklamalı etiketleri ve gönderilen commit'lerden erişilebilen olanları gönderir.
Uzak branch'i silme
Silme işlemi de push ile yapılır:
git push origin --delete feature/login
# eski söz dizimi, aynı işi yapar:
git push origin :feature/login
Yerel branch bu sırada kalır; onu git branch -d feature/login ile silebilirsiniz. Meslektaşlarınızda origin/feature/login işareti, onlar git fetch --prune çalıştırana kadar görünmeye devam eder.
Kullanışlı git push bayrakları
| Bayrak | Ne işe yarar |
|---|---|
-u, --set-upstream | Uzak branch'i upstream olarak kaydeder |
-n, --dry-run | Neyin gönderileceğini gösterir, hiçbir şey göndermez |
--all | Tüm yerel branch'leri gönderir |
--tags / --follow-tags | Etiketleri gönderir |
-d, --delete | Sunucudaki branch ya da etiketi siler |
--force-with-lease | Geçmişin güvenli yeniden yazımı |
-v, --verbose | Ayrıntılı çıktı |
--no-verify | pre-push kancasını atlar (bilinçli kullanın) |
git push'ta sık görülen hatalar ve çözümleri
Permission denied (publickey)
Sunucu SSH anahtarınızı kabul etmedi. Anahtarın var olduğunu (ls ~/.ssh), açık anahtarın hesaba eklendiğini ve bağlantının çalıştığını kontrol edin: ssh -T git@github.com. Remote HTTPS ile tanımlıysa Git anahtar yerine kullanıcı adı ve token ister; git remote -v ile bakın.
HTTPS ile Authentication failed
GitHub ve diğer birçok servis, HTTPS üzerinden çalışırken hesap parolasını uzun süredir kabul etmiyor. Kişisel bir erişim token'ı ya da SSH'ye geçiş gerekir. Token'ı saklamak için kimlik yardımcısı kullanabilirsiniz: git config --global credential.helper store (düz metin olarak saklar) ya da işletim sisteminizin kimlik bilgisi yöneticisi.
src refspec main does not match any
Bu adla bir branch'iniz yok. Çoğunlukla boş bir depoda henüz hiç commit yapılmamıştır ya da branch'in adı master'dır. git branch ile kontrol edin ve commit yapın ya da branch'i yeniden adlandırın: git branch -M main.
Everything up-to-date ama değişiklikler var
Commit yapmayı unutmuşsunuz. git push dosyaları değil commit'leri gönderir. git status ile bakın, sonra git add ve git commit yapın. Diğer bir olasılık, sunucuda görmeyi beklediğiniz branch'te olmamanızdır.
Dosya çok büyük
Servisler dosya boyutunu sınırlar (GitHub'da 100 MB). Böyle bir dosya geçmişe girdiyse, yeni bir commit ile silmek yetmez: geçmişi yeniden yazmanız ya da dosyayı henüz gönderilmemiş commit'lerden çıkarmanız gerekir (git reset --soft, sonra yeniden commit). Büyük ikili dosyalar için Git LFS kullanılır.
git push ile çalışma döngüsü
git switch -c feature/x— görev için branch.- Commit'ler küçük, mantıksal adımlarla.
git fetchvegit rebase origin/main— taze ana branch'i alın.git push -u origin feature/x— branch'i yayımlayın.- Pull request açın; inceleme sonrası ek commit'ler ve sıradan
git push. - Geçmişi yeniden yazmak zorunda kaldıysanız —
git push --force-with-lease.
Göndermeden önce neyin sunucuya gideceğine bakmak iyi bir alışkanlıktır: git log origin/main..HEAD --oneline, sunucuda henüz olmayan commit'leri listeler.
Bir kez ayarlanacaklar
Birkaç genel ayar, gönderirken çıkan sürprizlerin çoğunu önler. push.default, argümansız git push'un ne göndereceğini belirler. Güncel sürümlerde varsayılan simple'dır: yalnızca mevcut branch, yalnızca aynı adlı upstream branch'e gönderilir. Bunu değiştirmek genelde gerekmez, ama eski bir yapılandırmada matching kalmadığını kontrol edin; o, adı eşleşen tüm branch'leri aynı anda gönderir.
git config --global push.default simple
git config --global push.autoSetupRemote true
git config --global push.followTags true
git config --global pull.rebase true
push.followTags --follow-tags'i varsayılan davranış yapar; pull.rebase ise push reddedildiğinde önce başkalarının değişikliklerini alırken gereksiz birleştirme commit'lerinden kurtarır.
pre-push kancası
.git/hooks/pre-push dosyası gönderimden önce çalışır. Sıfır olmayan bir kodla biterse push gerçekleşmez. Ekipler buraya genellikle testleri ya da linter'ı koyar; böylece bozuk kod sunucuya ulaşmaz. --no-verify ile kancayı atlamak yalnızca neden başarısız olduğunu tam olarak bildiğinizde yapılmalıdır.
Kısaca
git push, commit'lerinizi uzak depoya yayımlar ve yalnızca tek yönde çalışır. Branch'in ilk gönderimini -u ile yapın; reddedilirse önce pull ile başkalarının işini alın; kendi branch'inizin yeniden yazılmış geçmişini yalnızca --force-with-lease ile gönderin. Uzak depolarla çalışma, push, pull ve SSH anahtarları Git kursunda uygulamalı olarak ele alınmaktadır.
Sık sorulan sorular
git push değiştirilmemiş dosyaları da gönderir mi?
Hayır. Push yalnızca commit'leri gönderir; çalışma dizinindeki ve index'teki değişiklikler siz commit edene kadar yerelde kalır.
git push'u nasıl geri alırım?
Kendi branch'inizde commit'i yerelde geri alıp (git reset) git push --force-with-lease ile gönderebilirsiniz. Ortak bir branch'te daha güvenlisi git revert ile ters bir commit oluşturup normal push yapmaktır.
Yalnızca bir commit'i gönderebilir miyim?
Evet, hash'ini vererek: git push origin abc1234:main o commit'e kadar olan tüm geçmişi gönderir, sonraki commit'leri göndermez. Bir commit atalarından bağımsız gönderilemez.
git push ile git push origin main arasındaki fark nedir?
Argümansız git push, mevcut branch'in ayarlı upstream'ini kullanır; açık biçim ise remote ve branch'i doğrudan belirtir ve upstream ayarlı olmasa bile çalışır.
Aynı anda iki depoya nasıl push yaparım?
İkinci bir remote ekleyip her birine adıyla gönderebilirsiniz; ya da origin'e iki push adresi ekleyin: git remote set-url --add --push origin adres. Bunu hem yeni adres hem de mevcut adres için yapmalısınız; aksi halde push yalnızca ikinciye gider.
Bu konu “Sıfırdan Güvenilir Geliştiriciye Git” kursunda uygulamalı olarak ayrıntılı işleniyor.
Kursa git