Belirtilen bir taahhüt nasıl değiştirilir?


2233

Genelde gözden geçirilmek üzere bir taahhüt listesi gönderirim. Aşağıdaki taahhütlerim varsa:

  1. HEAD
  2. Commit3
  3. Commit2
  4. Commit1

... kafa taahhüdünü değiştirebileceğimi biliyorum git commit --amend. Ancak taahhüt Commit1olmadığı göz önüne alındığında nasıl değişiklik yapabilirim HEAD?


31
Burada alternatif bir cevaba bakınız: stackoverflow.com/a/18150592/520567 Kabul edilen cevabınız sorunuzun tam cevabıdır, ancak düzenlemeyi kullanmaya karar vermeden önce yeni taahhüdünüzü hazır bulundurursanız, bu cevap daha basit olacaktır. Ayrıca, eski biriyle birleştirmek / ezmek istediğiniz birden fazla işlemle de çalışabilir.
akostadinov

6
Ayrıca sadece görebilirsiniz Bölme bir taahhüt içinde yeniden yazma Geçmiş - Git Tools fazla bilgi için.
hakre

Yanıtlar:


2955

Git rebase kullanabilirsiniz . Örneğin, kesinliği değiştirmek istiyorsanız bbc643cdçalıştırın

$ git rebase --interactive 'bbc643cd^'

Şapka unutmayın ^için aslında geri rebase gerek, çünkü komutun sonunda taahhüt önce Değiştirmek istediğiniz biri .

Varsayılan düzenleyici olarak, modifiye picketmek edit'bbc643cd' söz doğrultusunda.

Dosyayı kaydedin ve çıkın: git, dosyadaki komutları yorumlar ve otomatik olarak yürütür. Kendinizi, daha önce taahhütte bulunduğunuz önceki durumda bulacaksınız bbc643cd.

Bu noktada, bbc643cdson taahhüdünüzdür ve kolayca değiştirebilirsiniz : değişikliklerinizi yapın ve ardından komutla taahhüt edin:

$ git commit --all --amend --no-edit

Bundan sonra şunu yazın:

$ git rebase --continue

önceki HEAD taahhüdüne geri dönmek için.

UYARI : Bunun, söz konusu taahhüdün SHA-1'inin yanı sıra tüm çocukları değiştireceğini unutmayın - başka bir deyişle, bu, geçmişi o noktadan itibaren yeniden yazar. Komutu kullanarak iterseniz depoları kırabilirsinizgit push --force


125
Bu akıştaki bir başka ilginç seçenek, değiştirmek istediğiniz komuta geçtikten sonra, dosyaları değiştirmek ve üstteki taahhüdü (düzenlemekte olduğunuz) yerine karıştırmak yerine, bu taahhüdü iki farklı komiteye bölmek isteyebilirsiniz. (hatta daha fazlası). Bu durumda, düzenleme taahhüdüne geri dönün ve "git reset HEAD ^" komutunu çalıştırın. bu taahhüdün değiştirilmiş dosyalarını sahneye koyacaktır. Şimdi istediğiniz dosyaları seçin ve uygulayın. Bu akış "git-rebase" kılavuz sayfasında oldukça iyi açıklanmıştır. Bkz. "Bölme işlemleri" bölümü. bit.ly/d50w1M
Diego Pino

200
Git 1.6.6 ve daha yeni sürümlerde rewordeylemi git rebase -iyerine kullanabilirsiniz edit(düzenleyiciyi otomatik olarak açar ve geri kalan adım adımlarıyla devam eder; bu , içeriğin değil yalnızca taahhüt mesajının değiştirilmesi gerektiğini git commit --ammendve git rebase --continuegerektiğinde kullanılmasını engeller. ).
Chris Johnsen

108
Bekleyen değişiklikleriniz varsa, git stashönce git rebaseve git stash popsonra koşmanız gerekebileceğini belirtmek gerekir .
user123444555621

3
Düzenleyiciyi açmadan, taahhüdü bulmadan, düzenlemeyi işaretlemeden ve daha sonra komut satırına geri dönmeden etkileşimli rebase'de belirli bir komutu düzenlemek için bir shortucut komutu var mı?
sstur

15
Daha yeni git ile, git commit --all --amend --no-editburada körü körüne kullanmak yerine hızlı talimatlara uymanın daha akıllıca olacağını unutmayın . Sonra tek yapmam git rebase -i ...gereken git commit --amendnormalde o zaman git rebase --continue.
Eric Chen

453

Müthiş etkileşimli rebase'i kullanın:

git rebase -i @~9   # Show the last 9 commits in a text editor

İstediğiniz değişikliği işlemek bul pickiçin e( edit) ve kaydetmek ve yakın dosyası. Git bu taahhüde geri sarar ve şunlardan birini yapmanıza izin verir:

  • git commit --amenddeğişiklik yapmak için kullanın veya
  • git reset @~son değişikliği atmak için kullanın , ancak dosyadaki değişiklikleri değil (yani, dosyaları düzenlediğiniz, ancak henüz işlemediğiniz noktaya götürün).

İkincisi, birden fazla işleme bölmek gibi daha karmaşık şeyler yapmak için yararlıdır.

Ardından, çalıştırın git rebase --continueve Git, sonraki değişiklikleri değiştirilen taahhüdünüzün üzerine tekrar oynatır. Bazı birleştirme çakışmalarını düzeltmeniz istenebilir.

Not: belirtilen @kısayol için kısaltma HEADve ~taahhüttür.

Git belgelerinde yeniden yazma geçmişi hakkında daha fazla bilgi edinin .


Rebase'den korkma

ProTip ™: Geçmişi yeniden yazan "tehlikeli" komutları denemekten korkmayın * - Git varsayılan olarak 90 gün boyunca taahhütlerinizi silmez; Bunları reflogda bulabilirsiniz:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Gibi --hardve --forceolsa seçenekleri dikkat - veri atabilir.
* Ayrıca, birlikte çalıştığınız dallarda geçmişi yeniden yazmayın.



Birçok sistemde, git rebase -iVim'i varsayılan olarak açar. Vim modern metin editörlerinin çoğu gibi çalışmaz, bu yüzden Vim kullanarak nasıl yeniden pazarlayacağınıza bir göz atın . Farklı bir düzenleyici kullanmayı tercih ederseniz, ile değiştirin git config --global core.editor your-favorite-text-editor.


29
Cevabınızın ortası, sadece VIM için bir miniture reklamı olarak tanımlayabileceğim şeyi koymak için garip bir yer. Bu soru ile alakasız ve sadece cevabınızı karıştırıyor.
Intentss

21
@Intentss: Ah, bunun neden garip göründüğünü görebiliyorum. Bunun arkasındaki sebep, Vim'in birçok sistemde varsayılan metin editörü olmasıydı, bu yüzden birçok insanın interaktif yeniden baslamanın ilk deneyimi, yazmayı imlecin her yerde uçurduğu bir ekran. Ardından, editörlerini başka bir şeye değiştirirler ve ikinci etkileşimli yeniden baslama deneyimleri oldukça normaldir, ancak neden GUI yerine bir metin dosyası kullandığını merak eder. Yeniden temel alarak akış elde etmek için Vim veya Emacs'ın rebase modu gibi bir şeye ihtiyacınız var.
Zaz

9
Tamam. Pek çok insanın bu kısmı alakasız bulduğunu görünce, 3 satıra kadar yoğunlaştırdım ve gerektiğinde editörün nasıl değiştirileceğini de açıkladım.
Zaz

17
Müthiş! @Kestirme olarak kullanabileceğinizi bilmiyordum HEAD. Bunu gönderdiğiniz için teşekkürler.
James Ko

3
git reset @~tam olarak ne ben ile taahhüt seçtikten sonra yapmak istediğim git rebase .... Sen benim kahramanımsın)
18augst

79

Etkileşimli Rebase ile --autosquashben tarihin derin önceki kaydedilmesini fixup gerektiğinde ben sık kullandığınız bir şeydir. Temel olarak ZelluX'in cevabının gösterdiği süreci hızlandırır ve özellikle düzenlemek istediğiniz birden fazla taahhüdünüz olduğunda kullanışlıdır.

Belgelerden:

--autosquash

İşlem günlüğü mesajı "squash!…" (Veya "fixup!…") İle başladığında ve başlığı aynı ile başlayan bir işlem söz konusu olduğunda, rebase -i'nin yapılacaklar listesini otomatik olarak değiştirin. ezmek için işaretlenmiş, değiştirilme taahhüdünden hemen sonra gelir

Şöyle bir geçmişiniz olduğunu varsayın:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

ve Command2'de değiştirmek istediğiniz değişiklikleri yaptıktan sonra değişikliklerinizi

$ git commit -m "fixup! Commit2"

alternatif olarak, tamamlama mesajı yerine tamamlama komutunu, "fixup! e8adec4hatta tamamlama mesajının bir önekini kullanabilirsiniz.

Sonra daha önce taahhütte etkileşimli bir rebase başlatın

$ git rebase e8adec4^ -i --autosquash

editörünüz daha önce doğru şekilde sipariş edilmiş taahhütlerle açılır

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

yapmanız gereken tek şey kaydetmek ve çıkmak


21
Bunun git commit --fixup=@~yerine de kullanabilirsiniz git commit -m "fixup! Commit2". Bu özellikle taahhüt mesajlarınız daha uzun olduğunda ve her şeyi yazmanın bir yararı olduğunda faydalıdır.
Zaz

42

Çalıştırmak:

$ git rebase --interactive commit_hash^

her biri ^kaç tane geri düzenlemek istediğinizi belirtir, yalnızca bir tane (belirttiğiniz taahhüt karması) ise, yalnızca bir tane eklersiniz ^.

Vim kelimeleri değiştirmek kullanma pickiçin rewordkaydet göre, değişikliğe istediğiniz kaydedilmesini ve çıkmak ( :wq). Sonra git, reword olarak işaretlediğiniz her bir taahhüdü size soracaktır, böylece taahhüt mesajını değiştirebilirsiniz.

Kaydetmeniz ve çıkmanız gereken her taahhüt mesajı bir :wqsonraki taahhüt mesajına gitmek için ( )

Değişiklikleri uygulamadan çıkmak istiyorsanız, :q!

DÜZENLEME : gezinmek için vimkullandığınız jkadar gitmek, kaşağı gitmeye hsola gitmek ve l(bütün bu doğru gitmeye NORMALmoduna basın ESCgitmek için NORMALmod). Bir metni düzenlemek için, metin eklediğiniz moda igirmek için tuşuna basın INSERT. Moda ESCgeri dönmek için NORMALbasın :)

GÜNCELLEME : İşte git github listesinden harika bir bağlantı Git ile neredeyse her şeyi nasıl geri alabilirim (neredeyse)


4
Benim için mükemmel çalıştı. Bahsetmeye değer git push --forcemi?
u01jmg3

Ne git push --forceyapar, uzaktan kumandaların yerel taahhütleriniz üzerine yazmasıdır. Bu konu böyle değil :)
betoharres

@BetuUuUu Elbette, taahhütleriniz uzaktan kumandaya gönderildiyse ve yerel olarak taahhüt mesajını değiştirdiyseniz, uzaktan kumandaya zorla itmek istersiniz, değil mi?
Sudip Bhandari

@SudipBhandari Anladığım duygu bu. Zorlamadım ve şimdi, tüm taahhütleri mesajını değiştirdiğim kişiye geri yansıtan ekstra bir şubem var, ki bu çok çirkin.
ruffin

2
@greenhouse, değiştirir ve zorla iterseniz, diğer ekip üyeleri büyük olasılıkla birleşme çatışmalarıyla karşılaşır. Bu nedenle, genellikle bu konuda çok dikkatli olmalısınız. Ancak, henüz kimsenin getirmediği bir şeyi değiştirirseniz, iyi olmalıdır (fark etmeyecektir). Bu yüzden - kuvvetin son çare olduğunu düşünürdüm ve her zaman repo durumuna diğer üyelerle danışırım.
Tomasz Kaczmarzyk

18

Herhangi bir nedenle interaktif editörleri sevmiyorsanız kullanabilirsiniz git rebase --onto.

Değiştirmek istediğinizi söyleyin Commit1. İlk olarak, önce gelen şube Commit1:

git checkout -b amending [commit before Commit1]

İkinci Commit1olarak cherry-pick:

git cherry-pick Commit1

Şimdi, değişikliklerinizi değiştirin ve Commit1'şunları oluşturun :

git add ...
git commit --amend -m "new message for Commit1"

Ve son olarak, diğer değişiklikleri sakladıktan sonra, geri kalan taahhütlerinizi masteryeni taahhüdünüzün üzerine aktarın:

git rebase --onto amending Commit1 master

Okuyun: "şubeye yeniden inmek, (kapsayıcı olmayan) ve (kapsayıcı) amendingarasında değişmektedir ". Yani, Komut2 ve Komut3, eski Komut1'i tamamen ortadan kaldırır. Onları sadece kiraz toplayabilirsiniz, ancak bu şekilde daha kolaydır.Commit1master

Şubelerini temizlemeyi unutma!

git branch -d amending

4
git checkout -b amending Commit1~1önceki taahhüdü almak için kullanabilirsiniz
Arin Taylor

İlk iki adım eşit git checkout -b amending Commit1midir?
Haoshu

16

Belgelere Dayalı

Eski veya birden çok kesin mesajın mesajında ​​değişiklik yapma

git rebase -i HEAD~3 

Yukarıda, geçerli dalda son 3 taahhüdün bir listesi görüntülenir, daha fazlasını isterseniz 3'ü başka bir şeyle değiştirin. Liste aşağıdakine benzer olacaktır:

pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Değiştir almak ile reword her Değiştirmek istediğiniz iletiyi işlemek önce. Listedeki ikinci işlemi değiştirdiğinizi varsayalım, dosyanız aşağıdaki gibi görünecektir:

pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Kaydetme listesi dosyasını kaydedin ve kapatın, bu işlem tamamlama mesajınızı değiştirmek, tamamlama mesajını değiştirmek ve kaydetmek için yeni bir düzenleyici açılır.

Nihayet değiştirilen taahhütleri zorla itin.

git push --force

Aşağıdaki hatayı alıyorum: hata: 'vi' düzenleyicisinde bir sorun oluştu. Lütfen iletiyi -m veya -F seçeneğini kullanarak sağlayın.
Erick Maynard

12

Tamamen etkileşimli olmayan komut (1)

Sadece bunun için kullandığım bir takma adı paylaşacağımı düşündüm. Bu dayanıyor etkileşimli olmayan interaktif rebase. Gitinize eklemek için bu komutu çalıştırın (açıklama aşağıda verilmiştir):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'

Bu emrin en büyük avantajı vim olmamasıdır .


(1) Tabii ki rebase sırasında çatışma olmadığı için

kullanım

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

İsim amend-touygun görünüyor IMHO. Akışı şununla karşılaştırın --amend:

git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>

açıklama

  • git config --global alias.<NAME> '!<COMMAND>'- git <NAME>olmayan komutu çalıştıracak adlı genel bir git diğer adı oluşturur<COMMAND>
  • f() { <BODY> }; f - "anonim" bir bash işlevi.
  • SHA=`git rev-parse "$1"`; - bağımsız değişkeni git revizyonuna dönüştürür ve sonucu değişkene atar SHA
  • git commit --fixup "$SHA"- fixup-taahhüt etmek SHA. Dokümanlara bakıngit-commit
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" kısmı diğer cevaplar tarafından ele alınmıştır.
    • --autosquashile birlikte kullanılan şeydir git commit --fixup, daha fazla bilgi için git-rebasebelgelere bakın
    • GIT_SEQUENCE_EDITOR=trueher şeyi etkileşimli yapmayan şeydir. Bu kesmek bu blog yazısından öğrendim .

1
Bir de amend-tosaplanmamış dosyaları işleyebilir: git config --global alias.amend-to '!f() { SHA=git rev-parse "$ 1"; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
Dethariel

2
Bu yöntemle ilgili bir endişe, ilişkisiz düzeltmeleri uygulayabilmesidir.
Ciro Santilli 法轮功 18 审查 六四 事件 法轮功

Sorunun amacı tamamlama mesajını değiştirmek değil mi? Çünkü bu cevap buna değinmiyor ya da en azından doğrudan değil.
wytten

@wytten soru, tamamlama mesajının değiştirilmesi hakkında soru sormaz, HEAD olmayan taahhüdü değiştirmekle ilgilidir. Yani sorunuzun cevabı "hayır, sorunun konusu değil" olacaktır
Dethariel

Kafam karıştı, bu yüzden taahhüt mesajını nasıl değiştirebiliriz?
ggb667

8

Otomatik etkileşimli yeniden düzenleme düzenleme ve ardından bir geri dönüş için hazır geri alma

Kendim için bir senaryo yazdım yeterince sık bir geçmiş taahhüt tamir ederken buldum.

İşte iş akışı:

  1. git commit-edit <commit-hash>
    

    Bu sizi düzenlemek istediğiniz taahhütte bırakacaktır.

  2. Taahhüdü ilk etapta istediğiniz gibi düzeltin ve hazırlayın.

    ( git stash saveTaahhüt yapmadığınız dosyaları saklamak için kullanmak isteyebilirsiniz )

  3. Taahhüdü yeniden yapın --amend, örneğin:

    git commit --amend
    
  4. Rebase'i tamamlayın:

    git rebase --continue
    

Yukarıdakilerin çalışması için, aşağıdaki komut dosyasını git-commit-edit, sayfanızın herhangi bir yerinde çağrılan yürütülebilir bir dosyaya yerleştirin $PATH:

#!/bin/bash

set -euo pipefail

script_name=${0##*/}

warn () { printf '%s: %s\n' "$script_name" "$*" >&2; }
die () { warn "$@"; exit 1; }

[[ $# -ge 2 ]] && die "Expected single commit to edit. Defaults to HEAD~"

# Default to editing the parent of the most recent commit
# The most recent commit can be edited with `git commit --amend`
commit=$(git rev-parse --short "${1:-HEAD~}")
message=$(git log -1 --format='%h %s' "$commit")

if [[ $OSTYPE =~ ^darwin ]]; then
  sed_inplace=(sed -Ei "")
else
  sed_inplace=(sed -Ei)
fi

export GIT_SEQUENCE_EDITOR="${sed_inplace[*]} "' "s/^pick ('"$commit"' .*)/edit \\1/"'
git rebase --quiet --interactive --autostash --autosquash "$commit"~
git reset --quiet @~ "$(git rev-parse --show-toplevel)"  # Reset the cache of the toplevel directory to the previous commit
git commit --quiet --amend --no-edit --allow-empty  #  Commit an empty commit so that that cache diffs are un-reversed

echo
echo "Editing commit: $message" >&2
echo

7

Bu yaklaşıma geldi (ve muhtemelen interaktif rebase kullanmakla tamamen aynı), ancak benim için biraz basit.

Not: Bu yaklaşımı, günlük bir alternatiften ziyade neler yapabileceğinizi göstermek amacıyla sunuyorum. Birçok adım (ve muhtemelen bazı uyarılar) olduğundan.

Taahhüt değiştirmek istediğinizi 0ve şu anda devam ettiğinizi varsayalımfeature-branch

some-commit---0---1---2---(feature-branch)HEAD

Bu taahhüdü kontrol edin ve bir oluşturun quick-branch. Ayrıca özellik dalınızı kurtarma noktası olarak klonlayabilirsiniz (başlamadan önce).

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

Şimdi böyle bir şey olacak:

0(quick-branch)HEAD---1---2---(feature-branch)

Sahne değişiyor, her şeyi saklıyor.

git add ./example.txt
git stash

Değişiklikleri yapın ve ödeme işlemini tekrar yapın feature-branch

git commit --amend
git checkout feature-branch

Şimdi böyle bir şey olacak:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

Rebase feature-branchüzerine quick-branch(yol boyunca herhangi çatışmaları çözmek). Zımba uygulayın ve çıkarın quick-branch.

git rebase quick-branch
git stash pop
git branch -D quick-branch

Ve sonunda:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git, tekrarlama yaparken 0'ı ne ölçüde söyleyemesem de çoğaltmayacak.

Not: Tüm taahhüt karmaları, ilk başta değiştirmek istediğimiz taahhütten başlayarak değiştirilir.


6

Etkileşimli olmayan bir komut almak için PATH'nize bu içeriğe sahip bir komut dosyası ekleyin:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

Değişikliklerinizi (ile git add) hazırlayarak kullanın ve ardından çalıştırın git fixup <commit-to-modify>. Tabii ki, çatışma yaşarsanız hala etkileşimli olacaktır.


1
Bu iyi çalışıyor. Bir küme kümesini mükemmelleştirmek için kirli bir ağacın parça parça düzeltmelerini yapmak için ekstra işlevler ekledim. `dirtydiff = $ (git fark); eğer ["$ {dirtydiff}"! = ""]; sonra "Kirli ağacı saklamak" yankısı> & 2; git stash; fi;
Simon Feltman

6

git stash+ rebaseotomasyon

Gerrit incelemeleri için eski bir taahhüdü birçok kez değiştirmeniz gerektiğinde, yapıyorum:

git-amend-old() (
  # Stash, apply to past commit, and rebase the current branch on to of the result.
  current_branch="$(git rev-parse --abbrev-ref HEAD)"
  apply_to="$1"
  git stash
  git checkout "$apply_to"
  git stash apply
  git add -u
  git commit --amend --no-edit
  new_sha="$(git log --format="%H" -n 1)"
  git checkout "$current_branch"
  git rebase --onto "$new_sha" "$apply_to"
)

GitHub akış yukarı .

Kullanımı:

  • kaynak dosyayı değiştirmek, git addzaten repo varsa gerek yok
  • git-amend-old $old_sha

Bu --autosquashilgisiz diğer düzeltmeleri ezmek gibi değil gibi.


Çok güzel bir çözüm, bu git amendgeçerli saklamak kullanarak çok belirli bir taahhüt değişiklikleri uygulamak için varsayılan bir seçenek olmalıdır , çok zeki!
caiohamamura

5

Bunu çözdüm,

1) İstediğim değişikliklerle yeni taahhütler oluşturarak ..

r8gs4r commit 0

2) Onunla hangi taahhüdü birleştirmem gerektiğini biliyorum. taahhüt 3.

yani git rebase -i HEAD~4# 4 son 4 taahhüdü temsil etmektedir (burada taahhüt 3 dördüncü sıradadır)

3) etkileşimli rebase son taahhüt altta yer alacaktır. benzer görünecek,

pick q6ade6 commit 3
pick vr43de commit 2
pick ac123d commit 1
pick r8gs4r commit 0

4) Burada, belirli biriyle birleştirmek istiyorsanız, taahhüdü yeniden düzenlememiz gerekiyor. gibi olmalı,

parent
|_child

pick q6ade6 commit 3
f r8gs4r commit 0
pick vr43de commit 2
pick ac123d commit 1

yeniden sonra değiştirmek gerekir p pickile f( düzeltme mesajı taahhüt olmadan birleşecek) ya da s( kabak mesaj taahhüt ile birleştirme çalışma zamanında değiştirebileceğiniz)

ve sonra ağacınızı kaydedin.

şimdi mevcut taahhüt ile birleştirme yapılır.

Not: Kendi başınıza bakım yapmadığınız sürece tercih edilmeyen bir yöntemdir. Eğer büyük takım büyüklüğünüz varsa git ağacını yeniden yazmak için kabul edilebilir bir yöntem değil, diğer alışkanlıklarını bildiğiniz çatışmalarla sonuçlanacaktır. Eğer ağaç daha az taahhüt ile temiz tutmak istiyorsanız bunu deneyebilirsiniz ve onun küçük takım aksi takdirde onun tercih edilmez .....


Etkileşimli bir rebase sırasında canlı değişiklik yapmak istemiyorsanız, bu güzel bir çözümdür.
Dunatotatos

4

En iyi seçenek "Etkileşimli rebase komutu" kullanmaktır .

git rebaseKomut inanılmaz güçlüdür. Taahhüt mesajlarını düzenlemenizi , taahhütleri birleştirmenizi, yeniden sıralamanızı vb. Sağlar.

Bir taahhüdü her yeniden adlandırdığınızda, içerikten bağımsız olarak her taahhüt için yeni bir SHA oluşturulacaktır! Bu komutu ne zaman kullanacağınıza dikkat etmelisiniz, çünkü özellikle diğer geliştiricilerle işbirliği içinde çalışıyorsanız, önemli etkileri olabilir. Bazılarını yeniden temel alırken taahhüdünüzle çalışmaya başlayabilirler. Taahhütleri zorladıktan sonra senkronize olmayacaklar ve daha sonra dağınık bir durumda öğrenebilirsiniz. Yani dikkatli ol!

backupYeniden kontrol etmeden önce bir şube oluşturmanız önerilir, böylece her şeyi kontrolden çıkardığınızda önceki duruma geri dönebilirsiniz.

Şimdi bu komut nasıl kullanılır?

git rebase -i <base> 

-iayakta "interaktif" . Etkileşimli olmayan modda bir rebase gerçekleştirebileceğinizi unutmayın. örn:

#interactivly rebase the n commits from the current position, n is a given number(2,3 ...etc)
git rebase -i HEAD~n 

HEADgeçerli konumunuzu gösterir (ayrıca şube adı veya taahhütlü SHA olabilir). ~nVasıta "n beforeé, böylece HEAD~nşu anda bulunduğunuz birinden önce n 'kaydedilmesini listesini olacak'.

git rebase farklı komutları var:

  • pya da pickbağlılığını sürdürmek.
  • rveya reword: taahhüdün içeriğini tutmak, ancak taahhüt mesajını değiştirmek.
  • sveya squash: bu taahhüdün değişikliklerini önceki taahhütte birleştirmek (listede yukarıdaki taahhüt).
  • ... vb.

    Not: Git'in işleri kolaylaştırmak için kod düzenleyicinizle çalışmasını sağlamak daha iyidir. Mesela görsel kod kullanıyorsanız böyle ekleyebilirsiniz git config --global core.editor "code --wait". Ya da Google'da tercih ettiğiniz kod düzenleyicinizi GIT ile nasıl ilişkilendireceğinizi arayabilirsiniz.

Nın bir örneği git rebase

Bu şekilde işlem yaptığım son 2 taahhüdü değiştirmek istedim:

  1. Geçerli taahhütleri göster:
    #This to show all the commits on one line
    $git log --oneline
    4f3d0c8 (HEAD -> documentation) docs: Add project description and included files"
    4d95e08 docs: Add created date and project title"
    eaf7978 (origin/master , origin/HEAD, master) Inital commit
    46a5819 Create README.md
    
  2. Şimdi git rebaseson taahhüt mesajları 2 değiştirmek için kullanın : $git rebase -i HEAD~2 Bu kod editörü açar ve bunu göstermek:

    pick 4d95e08 docs: Add created date and project title
    pick 4f3d0c8 docs: Add project description and included files
    
    # Rebase eaf7978..4f3d0c8 onto eaf7978 (2 commands)
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    ...
    

    Ben bu 2 taahhüt mesajı değiştirmek istiyorum beri. Bu yüzden yazacağım rveya rewordyerine yazacağım pick. Sonra dosyayı kaydedin ve sekmeyi kapatın. rebaseÇok adımlı bir işlemde yürütüldüğünü unutmayın, böylece bir sonraki adım iletileri güncellemektir. Ayrıca, taahhütlerin ters kronolojik sırayla görüntülendiğine dikkat edin, böylece son işlem bir ve ilk işlemdeki ilk işlem görüntülenir.

  3. Mesajları güncelleyin: İlk mesajı güncelleyin:

    docs: Add created date and project title to the documentation "README.md"
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    ...
    

    kaydet ve kapat İkinci mesajı düzenle

    docs: Add project description and included files to the documentation "README.md"
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    ...
    

    kaydet ve kapat.

  4. Rebase'in sonuna kadar böyle bir mesaj alacaksınız: Successfully rebased and updated refs/heads/documentationbu da başarılı olduğunuz anlamına geliyor. Değişiklikleri görüntüleyebilirsiniz:

    5dff827 (HEAD -> documentation) docs: Add project description and included files to the documentation "README.md"
    4585c68 docs: Add created date and project title to the documentation "README.md"
    eaf7978 (origin/master, origin/HEAD, master) Inital commit
    46a5819 Create README.md
    

    Keşke bu yeni kullanıcılara yardımcı olabilir :).


2

Benim için bu, bir depodaki bazı kimlik bilgilerini kaldırmaktı. Yeniden temellendirmeyi denedim ve yeniden işlemeye çalışırken bir ton görünüşte ilgisiz çatışmalarla karşılaştım - devam et. Kendinizi yeniden denemeye çalışmayın, Mac'te BFG (brew install bfg) adlı aracı kullanın.


0

Taahhütleri henüz itmediyseniz, kullanarak önceki bir taahhüde geri dönebilirsiniz git reset HEAD^[1,2,3,4...]

Örneğin

git commit <file1> -m "Updated files 1 and 2"
git commit <file3> -m "Updated file 3"

Hata! İlk işleme dosya2'yi eklemeyi unuttum ...

git reset HEAD^1 // because I only need to go back 1 commit

git add <file2>

Bu işlem ilk işleme dosya2'yi ekleyecektir.


0

Bu çözüm çok aptalca gelebilir, ancak sizi belirli koşullarda kurtarabilir.

Bir arkadaşım yanlışlıkla çok büyük bazı dosyalar (her biri 3GB ila 5GB arasında değişen otomatik olarak oluşturulan dört dosya) kazara girdi ve daha sonra git pushartık çalışmayan sorunu fark etmeden önce bunun üzerine bazı ek kod taahhütleri yaptı !

Dosyalar listelenmiş .gitignoreancak kapsayıcı klasörü yeniden adlandırıldıktan sonra açığa çıkmış ve taahhüt edilmiştir! Ve şimdi bunun üzerine birkaç kod daha vardı, ancak pushsonsuza kadar çalışıyordu (GB veri yüklemeye çalışıyor!) Ve son olarak Github'un dosya boyutu sınırları nedeniyle başarısız oldu .

Etkileşimli rebase veya benzer bir şeyle ilgili sorun, bu büyük dosyaların etrafında dolaşmakla uğraşmaları ve sonsuza dek bir şey yapmalarıydı. Bununla birlikte, CLI'de neredeyse bir saat geçirdikten sonra, dosyaların (ve deltaların) gerçekten geçmişten kaldırıldığından veya yalnızca geçerli taahhütlere dahil edilmediğinden emin değildik. İtme de çalışmadı ve arkadaşım gerçekten sıkışmıştı.

Yani, bulduğum çözüm şuydu:

  1. Geçerli git klasörünü yeniden adlandırın ~/Project-old.
  2. Git klasörünü tekrar github'dan (kime ~/Project) klonlayın .
  3. Aynı şubeye ödeme yapın.
  4. El ile cp -rdosyalarından ~/Project-oldklasöre ~/Project.
  5. Teslim edilmesi gerekmeyen büyük dosyaların mvdüzenlendiğinden ve .gitignoredüzgün bir şekilde dahil edildiğinden emin olun.
  6. Ayrıca , eskisi tarafından .gitklonlanan klasördeki klasörün üzerine yazmadığınızdan emin olun ~/Project. Sorunlu tarihin kütükleri burada yaşar!
  7. Şimdi değişiklikleri gözden geçirin. Sorunlu dosyalar hariç, tüm son taahhütlerin birliği olmalıdır.
  8. Sonunda değişiklikleri yapın ve yapılması iyi olur push.

Bu çözümle ilgili en büyük sorun, bazı dosyaların manuel olarak kopyalanmasıyla ilgilidir ve ayrıca tüm son taahhütleri bir arada birleştirir (açıkçası yeni bir taahhüt ile).

En büyük faydaları, her adımda çok açık olması, büyük dosyalar (hassas dosyalar için olduğu kadar) için harika çalışması ve tarihte iz bırakmamasıdır!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.