Soru Git'te belirtilen bir taahhüt nasıl değiştirilir?


Genelde inceleme için bir taahhüt listesi gönderirim. Sahip olursam:

  • HEAD 
  • Commit3 
  • Commit2 
  • Commit1

Başlığı değiştirebileceğimi biliyorum. git commit --amendama nasıl değiştirebilirim Commit1, çünkü o değil HEAD taahhüt?


1704
2017-07-27 05:19


Menşei


Burada alternatif bir cevap bakın: stackoverflow.com/a/18150592/520567 Kabul ettiğiniz cevabınız gerçekten sorunuzun tam bir cevabıdır, ancak düzenlemeyi kullanmaya karar vermeden önce yeni taahhüdünüzü hazırladıysanız, bu cevap daha kolay olacaktır. Aynı zamanda, eski biriyle birleştirmek / ezmek istediğiniz birden fazla taahhütle de çalışabilir. - akostadinov
Ayrıca sadece görebilirsin Bir işlemi bölme içinde Git Araçları - Yeniden Yazma Tarihi daha fazla bilgi için. - hakre
Olası kopya Mevcut, işlenmemiş taahhütler nasıl değiştirilir? - tkruse


Cevaplar:


Git işlemini yeniden düzenlemek isterseniz, örneğin, yeniden düzenlemeyi kullanabilirsiniz. bbc643cd, koşmak

$ git rebase --interactive 'bbc643cd^'

Varsayılan düzenleyicide, değiştir pick için edit Taahhüdünü değiştirmek istediğiniz satırda. Değişikliklerinizi yapın ve daha önce sahip olduğunuzla aynı mesajı gönderin:

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

taahhüdünü değiştirmek ve bundan sonra

$ git rebase --continue

önceki kafaya geri dönmek.

UYARI: Bu işlemin SHA-1'ini değiştireceğini unutmayın. tüm çocuklar gibi Başka bir deyişle, bu tarihin bu noktadan ileriye doğru yeniden yazılması. Bunu yaparak reposları kırabilirsin komutu kullanarak zorlarsanız git push --force


2240
2017-07-27 05:28



Bu akıştaki bir başka ilginç seçenek de, dosyaları değiştirmek ve üzerinde değişiklik yapmak yerine (düzenleme yaptığınız kişi) değişiklik yapmak yerine, değiştirmek istediğiniz işleme geçtiğinizde, bu işlemi iki farklı işleme ayırmak isteyebilirsiniz. (ya da daha fazlası). Bu durumda, düzenleme isteğine geri dönün ve "git sıfırlama HEAD ^" komutunu çalıştırın. Bu işlemin değiştirilmiş dosyalarını sahneye koyacaktır. Şimdi istediğiniz gibi dosya seçin ve işleyin. Bu akış "git-rebase" man sayfasında oldukça iyi açıklanmıştır. "Bölme işlemleri" bölümüne bakın. bit.ly/d50w1M - Diego Pino
Git 1.6.6'da ve daha yenisini kullanabilirsiniz reword eylem git rebase -i yerine edit (otomatik olarak editörü açar ve rebase adımlarının geri kalanıyla devam eder; git commit --ammend ve git rebase --continue sadece içerik mesajını değil, içerik mesajını değiştirmeniz gerektiğinde). - Chris Johnsen
'Git rebase hash ^ --interactive' komutunu çalıştırdıktan sonra, '' commit commit --amend '' ifadesi, '' commit commit '' '' '' '' '' '' '' '' '' '' '' '' 'mesajı görüntüledikten sonra gerçek kodu değil. İşlenen kodu nasıl değiştirebilirim? Teşekkürler! - mikemaccana
Kaçman gerekebileceğine dikkat etmelisin. git stash önce git rebase ve git stash pop Daha sonra, bekleyen değişiklikleriniz varsa. - user123444555621
Daha yeni git ile, körü körüne kullanmak yerine komut istemlerini takip etmek akıllıca olacaktır. git commit --all --amend --no-edit İşte. Yapmam gereken tek şey git rebase -i ... oldu git commit --amend normalde o zaman git rebase --continue. - Eric Chen


Müthiş etkileşimli rebazı kullanın:

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

İstediğiniz taahhüdü bul, değiştir pick için e (edit) ve dosyayı kaydedip kapatın. Git, bu işlemi gerçekleştirecek ve aşağıdakileri yapmanıza izin verecek:

  • kullanım git commit --amend değişiklik yapmak için veya
  • kullanım git reset @~ Son işlemi iptal etmek, ancak dosyalarda yapılan değişiklikleri (yani, dosyaları düzenlediğinizde ve henüz işlem yapmadığınız sırada sizi götürecek şekilde) göz ardı etmek için.

İkincisi, çoklu taahhütlere bölmek gibi daha karmaşık şeyleri yapmak için yararlıdır.

O zaman koş git rebase --continueve Git, değiştirilen işleminizin üstündeki sonraki değişiklikleri tekrarlayacaktır. Bazı birleştirme çakışmaları düzeltmeniz istenebilir.

Not: @ için kısa HEAD, ve ~ belirtilen taahhütten önceki işlemdir.

Hakkında daha fazla bilgi edinin geçmişi yeniden yazma Git dokümanlarında.


Yeniden doğmaktan korkma

ProTip: Geçmişi yeniden yazan "tehlikeli" komutları denemekten korkmayın * - Git, taahhütlerinizi varsayılan olarak 90 gün boyunca silmez; onları 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 seçenekler için dikkat edin --hard ve --force olsa da - verileri atabilirler.
* Ayrıca, üzerinde çalıştığınız tüm dallarda geçmişi yeniden yazmayın.



Birçok sistemde git rebase -i varsayılan olarak Vim'i açacaktır. Vim çoğu modern metin editörü gibi çalışmıyor, o yüzden bir göz atın Vim kullanarak nasıl yeniden üretilir. Farklı bir editör kullanmayı tercih ederseniz, git config --global core.editor your-favorite-text-editor.


304
2018-04-29 17:50



Cevabınızın ortası, sadece VIM için bir miniture ilanı olarak tanımlayabileceğim bir şey koymak için garip bir yer. Bu soruyla alakasız ve sadece cevabınızı karıştırıyor. - Intentss
@Intentss: Ah, bunun neden garip göründüğünü anlayabiliyorum. Bunun arkasındaki mantık, Vim'in birçok sistemde varsayılan metin editörü olmasıydı, bu yüzden birçok kişinin ilk interaktif yeniden oluşturma deneyimi, yazmanın imlecin her yere yayılmasını sağlayan bir ekran. Daha sonra editörlerini başka bir şeye dönüştürürler ve ikinci interaktif yeniden oluşturma deneyimi oldukça normaldir, ancak neden bir GUI yerine bir metin dosyası kullandığını merak ederek bırakır. Rebasing ile akışa ulaşmak için Vim veya Emacs rebase-mode gibi bir şeye ihtiyacınız var. - Zaz
Gedit ya da nano gibi bir şeyi interaktif rebase'e kullanmak zorunda kalsaydım, çok daha az yeniden rebase ederdim. Belki bu biraz kötü bir şey olmaz, çünkü ben bir rebase bağımlısıyım. - Zaz
Tamam. Bu kadar çok insanın ilgisiz olduğunu görünce 3 sıraya yoğunlaştırdım ve eğer gerekiyorsa editörün nasıl değiştirileceğini de açıkladım. - Zaz
Korku veren! Kullanabileceğini bilmiyordum @ kestirme olarak HEAD. Bunu gönderdiğiniz için teşekkürler. - James Ko


interaktif rebase ile --autosquash Geçmişte daha önce yapılan işleri daha fazla düzeltmem gerektiğinde sık kullandığım bir şeydir. Aslında ZelluX'un yanıtının gösterdiği süreci hızlandırır ve düzenlemeniz gereken birden fazla işleminiz olduğunda özellikle kullanışlıdır.

Belgelerden:

--autosquash

Işlem günlüğü mesajı "squash!…" (Veya "fixup!…") İle başladığında, ve başlıkları aynı ile başlayan bir taahhüt var…, rebase-i yapılacaklar listesi otomatik olarak değiştirilir. Eskime için işaretlenmiş, tadilatın değiştirilmesinden hemen sonra gelir

Şuna benzeyen bir geçmişiniz olduğunu varsayalım:

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

ve Commit2'ye geçmek istediğiniz değişiklikleri yapın, ardından değişikliklerinizi kullanarak

$ git commit -m "fixup! Commit2"

alternatif olarak, taahhüt mesajının yerine commit-sha kullanabilirsiniz. "fixup! e8adec4 hatta taahhüt mesajının sadece bir öneki.

Daha sonra, taahhütte etkileşimli bir rebase başlatın

$ git rebase e8adec4^ -i --autosquash

Düzenleyiciniz, doğru şekilde sipariş edilmiş olan siparişlerle açılacak

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

Tek yapmanız gereken kaydetmek ve çıkmak


57
2017-09-29 17:59



Ayrıca kullanabilirsiniz git commit --fixup=@~ yerine git commit -m "fixup! Commit2". Bu özellikle taahhüt mesajlarınız daha uzun olduğunda ve her şeyi yazarken bir acı çekmesi durumunda faydalıdır. - Zaz


Koşmak:

$ git rebase --interactive commit_hash^

her ^ Düzenlemek istediğiniz geri yükleme sayısını gösterir. Yalnızca bir tane (belirttiğiniz taahhüt kümesi) ise, yalnızca bir tane eklersiniz. ^.

Vim kullanarak kelimeleri değiştirirsiniz pick için reword Değiştirmek istediğiniz kayıtlar için kaydedin ve çıkın (:wq). Daha sonra git, reword olarak işaretlediğiniz her bir taahhütte sizi uyaracaktır, böylece taahhüt mesajını değiştirebilirsiniz.

Kaydetmek ve çıkmak zorunda olduğunuz her bir taahhüt mesajı (:wq) Bir sonraki taahhüt mesajına gitmek

Değişiklikleri uygulamadan çıkmak isterseniz, tuşuna basın. :q!

DÜZENLE: içinde gezinmek vim kullan j kadar gitmek, k Aşağı inmek, h sola gitmek, ve l sağa gitmek için (tüm bunları NORMAL modu, tuşuna basın ESC gitmek için NORMAL mod). Bir metni düzenlemek için i böylece sen gir INSERT metin eklediğiniz yer. Basın ESC geri dönmek NORMAL modu :)

GÜNCELLEŞTİRME: İşte github listesinden harika bir link Git (hemen hemen) bir şey ile nasıl geri alınır 


30
2017-07-02 19:11



Benim için mükemmel çalıştı. Bahsetmeye değer git push --force? - u01jmg3
Ne git push --force remo'ların yerel işlemlerinizle birlikte üzerine yazılmasını sağlar. Bu konu bu değil :) - betoharres
@BetuUuUu, eğer işlemleriniz uzaktan yönlendirilirse ve yerel olarak değiştirilmiş mesajınızı değiştirdiyseniz, uzaktan kumandayı zorlamak isteyebilirsiniz, değil mi? - Sudip Bhandari
@SudipBhandari Bu aldığım duygu. Zorlamadım, şimdi de fazladan bir şubem var, tüm taahhütleri mesajımı değiştirdiğim tarafa yansıtıyorum, ki bu çok çirkin. - ruffin
Etkileşimli rebase başlangıçta zor görünebilir. Ben ayrıntılı olarak, adım adım sunan bir yazı (resimlerle) yazdım: blog.tratif.com/2018/04/19/the-power-of-git-interactive-rebase - Tomasz Kaczmarzyk


Eğer bir sebepten dolayı etkileşimli editörleri sevmiyorsanız git rebase --onto.

Değiştirmek istediğini söyle Commit1. İlk olarak, şubeden önce  Commit1:

git checkout -b amending [commit before Commit1]

İkincisi, kapmak Commit1 ile cherry-pick:

git cherry-pick Commit1

Şimdi değişikliklerinizi düzeltin, yaratın Commit1':

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

Ve son olarak, başka herhangi bir değişiklik yaptıktan sonra, taahhütlerinizi geri kalanına nakletmek master üstünde senin yeni taahhüt:

git rebase --onto amending Commit1 master

Oku: "dalın üzerine, rebad amendingarasındaki tüm taahhütler Commit1 (dahil olmayan) ve master (kapsayıcı) ". Yani, Commit2 ve Commit3, eski Commit1'i tamamen kesiyorlar. Onları sadece vişne alabilirsin, ama bu şekilde daha kolay.

Dallarını temizlemeyi unutma!

git branch -d amending

12
2017-10-22 12:19



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


Bu yaklaşıma geldim (ve muhtemelen etkileşimli rebase kullanmakla tamamen aynıdır) ama benim için çok basit.

Not: Bu yaklaşımı, günlük bir alternatiften ziyade yapabileceğiniz şeylerin gösteriminde sunarım. Birçok adımı olduğu için (ve muhtemelen bazı uyarılar.)

İşlemi değiştirmek istediğini söyle 0 ve şu an feature-branch

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

Bu işlem için ödeme yapın ve quick-branch. Ayrıca, özellik dalınızı bir kurtarma noktası olarak (başlamadan önce) kopyalayabilirsiniz.

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

Şimdi böyle bir şeye sahip olacaksınız:

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

Sahne değişiklikleri, diğer her şeyi sakla.

git add ./example.txt
git stash

Değişiklikleri ve geri ödeme işlemlerini gerçekleştirin feature-branch

git commit --amend
git checkout feature-branch

Şimdi böyle bir şeye sahip olacaksınız:

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

rebase feature-branch üstüne quick-branch (yol boyunca herhangi bir anlaşmazlığı çözer). Stash uygula ve kaldır quick-branch.

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

Ve sonuçta:

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

Git, kopyalamanın ne zaman gerçekleşeceğini (ne ölçüde söyleyemesem de) çoğaltamaz.

Not: Tüm taahhüt karmaları, orijinal olarak değiştirmeyi planladığımız taahhütten başlayarak değiştirilir.


6
2018-06-01 11:57





Etkileşimli olmayan bir komut almak için, bu içeriğe PATH'nizde bir komut dosyası koyun:

#!/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 hazırlayarak kullanın (ile git add) ve sonra koş git fixup <commit-to-modify>. Elbette çatışmalar yaşarsanız etkileşimli olacaktır.


4
2018-01-16 15:27



Bu iyi çalışıyor. Bir taahhüt setini mükemmelleştirmek için kirli bir ağacın parçalı düzeltmelerini yapmak için bazı ekstra işlevler ekledim. `dirtydiff = $ (git farklılığı); eğer ["$ {dirtydiff}"! = ""]; daha sonra "Stashing dirty tree"> & 2; git stash; fi; - Simon Feltman


Tamamen etkileşimli olmayan komut(1)

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

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 komutun en büyük avantajı, onun no-vim.


(1)rebase sırasında herhangi bir çatışma olmadığı göz önüne alındığında

kullanım

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

İsim amend-to uygun IMHO görünüyor. Akışı ile 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>' - adında küresel bir hedef takma adı oluşturur <NAME> git-olmayan komutu yürütecek <COMMAND>
  • f() { <BODY> }; f - "anonim" bir bash işlevi.
  • SHA=`git rev-parse "$1"`; - argümanı git revizyonuna dönüştürür ve sonucu değişkene atar SHA
  • git commit --fixup "$SHA" - düzeltmek için SHA. Görmek git-commit docs
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" bölüm diğer cevaplar tarafından ele alınmıştır.
    • --autosquash ne ile birlikte kullanılır git commit --fixup, görmek git-rebase docs daha fazla bilgi için
    • GIT_SEQUENCE_EDITOR=true her şeyi interaktif olmayan şeydir. Bu hack öğrendim bu blog gönderisinden.

4
2018-02-27 01:47



Biri de yapabilir amend-to sınıflandırılmamış dosyaları işlemek: 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
Onu kullanıyorum --autostash rebase komutunda bayrak. - idanp


Benim için bir repodan bazı kimlik bilgilerinin kaldırılmasıydı. Rebasing'i denedim ve rebase --continue yapmaya çalışırken yol boyunca görünüşte birbiriyle ilgisiz çatışmalara rastladım. Kendinizi yeniden yaratmaya teşebbüs etmeyin, Mac'te BFG (brew install bfg) adlı aracı kullanın.


1
2017-11-07 07:24





Bunu çözdüm

1) istediğim değişikliklerle yeni taahhütler yaratarak ..

r8gs4r commit 0

2) Hangi birleşmeyi onunla birleştirmem gerektiğini biliyorum. bu da 3.

yani, git rebase -i HEAD~4 # 4 son 4 taahhüdünü temsil ediyor (burada 3. sırada 4. sırada yer alıyor)

3) interaktif rebase içinde son taahhüt altta yer alacak. aynı görünecek

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

4) Burada spesifik olanla birleştirmek istiyorsanız, bu işlemi yeniden düzenlemeliyiz. gibi olmalı

parent
|_child

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

yeniden düzenledikten sonra değiştirmeniz gerekir p  pick ile f (onarmak taahhütte bulunmadan birleştirilecek) veya s (kabak taahhüt mesajı ile birleştirmek çalışma zamanında değişebilir)

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

Şimdi mevcut taahhüt ile birleştirin.

Not: Kendi başınıza devam etmediğiniz sürece tercih edilen yöntem değildir. Eğer   büyük bir takım büyüklüğüne sahipsin, git yeniden yazmak için kabul edilebilir bir yöntem değil   Ağaç, başkalarını bildiğin çatışmalarda bitecek. Eğer istersen   daha az taahhütle ağacı temiz tutmak için bunu deneyebilirsiniz ve eğer   küçük takım aksi takdirde tercih edilmez .....


1
2018-01-05 18:35



Interaktif bir rebase sırasında canlı modifikasyon yapmak istemiyorsanız, bu hoş bir çözümdür. - Dunatotatos


Dayalı belgeleme

Eski veya birden çok taahhütlü mesajın mesajını değiştirme

git rebase -i HEAD~3 

Yukarıdakiler, mevcut şube üzerindeki son 3 işlemin bir listesini görüntüler, daha fazlasını isterseniz başka bir şeye 3 değiştirir. Liste aşağıdakine benzer görünecektir:

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

değiştirmek almak ile başka kelimelerle ifade etmek Her bir taahhüt mesajından önce değiştirmek istiyorsunuz. Listede 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.

Kayıt listesi dosyasını kaydedin ve kapatın, bu sizin taahhüt mesajınızı değiştirmek, taahhüt mesajını değiştirmek ve kaydetmek için yeni bir editör açacaktır.

Son Kuvvet zorla değiştirilmiş işlemleri itin.

git push --force

0
2018-05-17 08:38