지정된 커밋을 수정하는 방법?


2233

나는 보통 검토를 위해 커밋 목록을 제출합니다. 다음 커밋이있는 경우 :

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

...로 헤드 커밋을 수정할 수 있다는 것을 알고 있습니다 git commit --amend. 그러나 커밋 Commit1이 아닌 경우 어떻게 수정할 수 HEAD있습니까?


31
다른 답변은 여기를 참조하십시오 : stackoverflow.com/a/18150592/520567 수락 된 답변은 실제로 귀하의 질문에 대한 정확한 답변이지만 편집을 사용하기로 결정하기 전에 새로운 커밋을 준비한 경우이 답변이 더 간단합니다. 또한 이전 커밋과 병합 / 스쿼시하려는 여러 커밋을 사용할 수도 있습니다.
akostadinov

6
또한 자세한 내용 Git 도구-기록 기록 에서 커밋 분할 을 참조하십시오.
hakre

답변:


2955

git rebase 사용할 수 있습니다 . 예를 들어 commit을 수정 bbc643cd하려면 다음을 실행하십시오.

$ git rebase --interactive 'bbc643cd^'

커밋 을 수정 하기 전에^ 실제로 커밋 해야하기 때문에 명령 끝에 캐럿 을 기록하십시오 .

기본 편집기에서 수정 pickedit'bbc643cd'를 언급 라인에.

파일을 저장하고 종료합니다 : git은 파일의 명령을 해석하고 자동으로 실행합니다. 커밋을 만든 이전 상황에서 자신을 발견 할 수 있습니다 bbc643cd.

이 지점에서, bbc643cd 마지막 커밋이 있으며 쉽게 수정할있습니다 . 변경 한 후 다음 명령으로 커밋하십시오.

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

그런 다음 다음을 입력하십시오.

$ git rebase --continue

이전 HEAD 커밋으로 돌아갑니다.

경고 : 이렇게하면 해당 커밋의 SHA-1 과 모든 자식 이 변경됩니다. 즉,이 시점부터 기록을 다시 작성합니다. 명령을 사용하여 밀어 넣으면 이 작업을 수행 할 수 있습니다.git push --force


125
이 흐름의 또 다른 흥미로운 옵션은 파일을 수정하지 않고 수정하려는 커밋으로 이동하고 커밋 (편집중인 커밋) 위에 확장 한 다음 해당 커밋을 두 개의 다른 커밋으로 분할 할 수 있습니다 (또는 그 이상). 이 경우 커밋으로 다시 이동하여 "git reset HEAD ^"를 실행하십시오. 커밋의 수정 된 파일을 스테이지에 넣습니다. 이제 원하는대로 파일을 선택하고 커밋하십시오. 이 흐름은 "git-rebase"매뉴얼 페이지에 잘 설명되어 있습니다. "커밋 분할"섹션을 참조하십시오. bit.ly/d50w1M
Diego Pino

200
망할 놈의 1.6.6에서 더 새로운 당신이 사용할 수 reword에 조치를 git rebase -i대신 edit(자동으로 편집기를 열고 REBASE 단계의 나머지 부분을 계속, 이것은의 사용을 미연에 방지 git commit --ammend하고 git rebase --continue만 변경해야 할 때 메시지가 아닌 내용을 커밋 ).
Chris Johnsen

108
당신이 실행해야 할 수도 있다는 지적이의 가치가 git stash이전 git rebasegit stash pop는 보류중인 변경 한 경우, 나중에.
user123444555621

3
편집기를 열지 않고 커밋을 찾고 편집 한 다음 명령 줄로 다시 가져 가지 않고 대화식 리베이스에서 특정 커밋을 편집하는 바로 가기 명령이 있습니까?
sstur

15
최신 git에서는 맹목적으로 사용하는 대신 프롬프트 지시를 따르는 것이 현명합니다 git commit --all --amend --no-edit. 내가해야 할 일은 보통 그때뿐 git rebase -i ...이었습니다 . git commit --amendgit rebase --continue
Eric Chen

452

멋진 대화식 리베이스를 사용하십시오.

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

1, 당신이 원하는 변화를 커밋 찾기 picke( edit), 저장하고 파일을 닫습니다. Git은 해당 커밋으로 되 감아 다음 중 하나를 수행 할 수 있습니다.

  • 사용하다 git commit --amend변경하는 데 하거나
  • git reset @~파일의 변경 사항이 아닌 마지막 커밋을 버리는 데 사용 하십시오 (즉, 파일을 편집했지만 아직 커밋하지 않은 시점으로 이동하십시오).

후자는 여러 커밋으로 분할하는 것과 같이 더 복잡한 작업을 수행하는 데 유용합니다.

그런 다음을 실행 git rebase --continue하면 Git은 수정 된 커밋 위에 후속 변경 사항을 재생합니다. 일부 병합 충돌을 수정하라는 메시지가 표시 될 수 있습니다.

참고 : @대한 속기 HEAD, 그리고 ~커밋 지정하기 전에 커밋이다.

Git 문서에서 기록다시 작성 하는 방법에 대해 자세히 알아보십시오 .


리베이스를 두려워하지 마십시오

ProTip ™ : 기록을 다시 작성하는 "위험한"명령을 실험하는 것을 두려워하지 마십시오 * — Git은 기본적으로 90 일 동안 커밋을 삭제하지 않습니다. reflog에서 찾을 수 있습니다.

$ 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

* 같은 옵션을 조심 --hard하고 --force있지만 - 그들은 데이터를 삭제할 수 있습니다.
* 또한 공동 작업중인 지점의 기록을 다시 쓰지 마십시오.



많은 시스템에서 git rebase -i기본적으로 Vim이 열립니다. Vim은 대부분의 최신 텍스트 편집기처럼 작동하지 않으므로 Vim을 사용하여 리베이스하는 방법을 살펴보십시오 . 다른 편집기를 사용하려면로 변경하십시오 git config --global core.editor your-favorite-text-editor.


29
답의 중간에는 VIM의 미니어처 광고로만 설명 할 수있는 것을 넣을 수있는 이상한 곳입니다. 질문과 관련이 없으며 답변을 어수선하게 만듭니다.
의도

21
@ 의도 : 아, 왜 이상하게 보 였는지 알 수 있습니다. Vim은 많은 시스템에서 기본 텍스트 편집기이기 때문에 많은 사람들이 대화식 rebasing에 대한 첫 경험은 타이핑하면 커서가 모든 곳에서 날아 다니는 화면입니다. 그런 다음 편집기를 다른 것으로 바꾸고 대화식 rebasing에 대한 두 번째 경험은 상당히 정상이지만 GUI 대신 텍스트 파일을 사용하는 이유가 궁금합니다. 리베이스로 흐름을 달성하려면 Vim 또는 Emacs의 리베이스 모드와 같은 것이 필요합니다.
Zaz

9
괜찮아. 많은 사람들이 해당 부분이 관련이 없다는 것을 알았으므로 3 줄로 압축하고 필요한 경우 편집기를 변경하는 방법도 설명했습니다.
Zaz

17
대박! 나는 당신이 @속기로서 사용할 수 있다는 것을 몰랐 습니다 HEAD. 이것을 게시 해 주셔서 감사합니다.
제임스 코

3
git reset @~커밋을 선택한 후 정확히하고 싶은 일 git rebase .... 당신은 나의 영웅입니다)
18 Aug

79

대화 형 REBASE--autosquash 는 이전 커밋을 기록에서 더 깊이 수정해야 할 때 자주 사용하는 것입니다. 본질적으로 ZelluX의 답변이 보여주는 프로세스의 속도를 높이고 편집해야 할 커밋이 둘 이상인 경우 특히 유용합니다.

설명서에서 :

--autosquash

커밋 로그 메시지가 "squash! ..."(또는 "fixup!…")로 시작하고 제목이 같은 것으로 시작하는 커밋이있는 경우 rebase -i의 할 일 목록을 자동으로 수정하여 커밋 커밋 수정 직후 스 쿼싱으로 표시

다음과 같은 히스토리가 있다고 가정하십시오.

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

Commit2로 수정하고 변경 사항을 커밋하려는 변경 사항이 있습니다.

$ git commit -m "fixup! Commit2"

또는 commit 메시지 대신 commit-sha를 사용할 수 있습니다. "fixup! e8adec4또는 하거나 의 접두사를 사용할 수도 있습니다.

그런 다음 커밋에서 대화식 리베이스를 시작하십시오.

$ git rebase e8adec4^ -i --autosquash

커밋이 이미 올바르게 정렬되어 편집기가 열립니다.

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

저장하고 종료하기 만하면됩니다.


21
git commit --fixup=@~대신에 사용할 수도 있습니다 git commit -m "fixup! Commit2". 커밋 메시지가 길고 모든 것을 입력하는 것이 어려울 때 특히 유용합니다.
Zaz

42

운영:

$ git rebase --interactive commit_hash^

각각 ^은 편집하려는 커밋 수를 나타냅니다. 단 하나의 커밋 해시 인 경우 하나만 추가하면 ^됩니다.

Vim을 사용하면 변경, 저장 및 quit ( ) 하려는 커밋 pickreword대한 단어 를 변경합니다 :wq. 그런 다음 git은 reword로 표시된 각 커밋을 묻는 메시지를 표시하여 커밋 메시지를 변경할 수 있습니다.

각 커밋 메시지는 저장하고 quit ( :wq)해야 다음 커밋 메시지로 이동합니다.

변경 사항을 적용하지 않고 종료하려면 :q!

편집 : 탐색하기 위해 vim사용 j올라가고, k내려 가서 h왼쪽으로 이동을하고, l(이 모든 것이 바로 갈 NORMAL모드를 눌러 ESC로 이동하는 NORMAL모드). 텍스트를 편집하려면 을 눌러 텍스트를 삽입 할 모드로 i들어갑니다 INSERT. 모드 ESC로 돌아가려면 누르십시오 NORMAL:)

업데이트 : github 리스팅의 훌륭한 링크는 다음과 같습니다 .git으로 무엇이든 (거의) 실행 취소하는 방법


4
나를 위해 완벽하게 일했습니다. 언급 할 가치가 git push --force있습니까?
u01jmg3

어떤 git push --force일은 해당 지역의 커밋으로 리모컨의 커밋을 덮어 쓸 수 있습니다. 그것은이 주제의 경우가 아니다 :)
betoharres

@BetuUuUu 물론 커밋이 원격으로 푸시되고 커밋 메시지를 로컬로 수정 한 경우 강제로 원격으로 푸시하고 싶습니까?
Sudip Bhandari

@SudipBhandari 그것이 내가 얻는 느낌입니다. 나는 강요하지 않았으며 이제 여분의 지점이있어 모든 커밋을 내가 메시지를 변경 한 사람에게 다시 반영합니다.
ruffin

2
@greenhouse 수정하고 강제 푸시하면 다른 팀 구성원이 병합 충돌을 경험하게 될 것입니다. 따라서 일반적으로 신중해야합니다. 그러나 아직 다른 사람이 가져 오지 않은 것을 수정하면 괜찮을 것입니다. 그래서 --force를 최후의 수단으로 생각하고 항상 다른 회원들과 레포의 상태를 상담하십시오.
Tomasz Kaczmarzyk 2016 년

18

어떤 이유로 대화 형 편집기가 마음에 들지 않으면을 사용할 수 있습니다 git rebase --onto.

수정한다고 가정 해보십시오 Commit1. 먼저 이전 에서 분기 Commit1:

git checkout -b amending [commit before Commit1]

둘째 Commit1cherry-pick:

git cherry-pick Commit1

이제 변경 사항을 수정하여 다음을 작성하십시오 Commit1'.

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

마지막으로 다른 변경 사항을 저장 한 후 나머지 커밋을 master새 커밋 위에 이식하십시오 .

git rebase --onto amending Commit1 master

읽기 : "브랜치에 리베이스 ( amending모두 Commit1비 포함)와 master(포함) 사이의 모든 커밋 " 즉, Commit2 및 Commit3은 이전 Commit1을 완전히 제거합니다. 당신은 그들을 체리 따기 할 수 있지만,이 방법은 더 쉽습니다.

가지를 청소하십시오!

git branch -d amending

4
당신은 git checkout -b amending Commit1~1사전 커밋을 얻기 위해 사용할 수 있습니다
Arin Taylor

처음 두 단계는과 동일 git checkout -b amending Commit1합니까?
Haoshu

16

문서를 기반으로

이전 또는 여러 커밋 메시지의 메시지 수정

git rebase -i HEAD~3 

위는 현재 브랜치에서 마지막 3 개의 커밋 목록을 표시합니다. 더 많은 것을 원하면 3을 다른 것으로 변경하십시오. 목록은 다음과 유사합니다.

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

선택reword로 교체 각각 변경하려는 메시지를 커밋하기 전에. 목록에서 두 번째 커밋을 변경한다고 가정하면 파일은 다음과 같습니다.

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

커밋 목록 파일을 저장하고 닫으면 커밋 메시지를 변경하고 커밋 메시지를 변경하고 저장할 수있는 새 편집자가 나타납니다.

Finaly 수정 된 커밋을 강제로 푸시합니다.

git push --force

다음과 같은 오류가 발생합니다. error : 편집기 'vi'에 문제가 있습니다. -m 또는 -F 옵션을 사용하여 메시지를 제공하십시오.
Erick Maynard

12

완전 비 대화식 명령 (1)

방금 내가 사용하는 별칭을 공유한다고 생각했습니다. 비 대화식 대화 형 rebase를 기반으로 합니다. git에 추가하려면이 명령을 실행하십시오 (아래 설명).

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'

이 명령의 가장 큰 장점은 명령이 no-vim 이라는 사실입니다 .


(1) 물론 재베이스 중에 충돌이 없음을 감안할 때

용법

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

이름 amend-to은 적절한 IMHO로 보인다. 흐름을 --amend다음 과 비교하십시오 .

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

설명

  • git config --global alias.<NAME> '!<COMMAND>'-git <NAME>이 아닌 명령을 실행할 전역 git 별명을 만듭니다.<COMMAND>
  • f() { <BODY> }; f - "익명"bash 함수.
  • SHA=`git rev-parse "$1"`; -인수를 git 개정으로 변환하고 결과를 변수에 할당 SHA
  • git commit --fixup "$SHA"-에 대한 fixup-commit SHA. 문서 보기git-commit
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" 부분은 다른 답변으로 덮여 있습니다.
    • --autosquash와 함께 사용되는 것 입니다. 자세한 git commit --fixup내용은 git-rebase문서 를 참조하십시오.
    • GIT_SEQUENCE_EDITOR=true전체를 비 대화식으로 만드는 것입니다. 이 해킹 은이 블로그 게시물에서 배웠 습니다 .

1
하나는 만들 수 있습니다 amend-to핸들 unstaged 파일 : git config --global alias.amend-to '!f() { SHA=자식 레브 - 구문 분석 "$ 1"; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
Dethariel

2
이 방법의 한 가지 우려는 관련없는 수정을 적용 할 수 있다는 것입니다.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

커밋 메시지를 변경하는 것이 중요하지 않습니까? 이 답변은 그것을 해결하지 못하거나 적어도 직접적으로는 아닙니다.
wytten December

@ wytten 커밋 메시지를 변경하는 것에 대해 질문하지 않고 커밋을 수정하는 것이 HEAD가 아닙니다. 따라서 귀하의 질문에 대한 답변은 "아니오, 그것은 문제의 요점이 아닙니다"
Dethariel

혼란스러워서 커밋 메시지를 어떻게 변경합니까?
ggb667

8

자동화 된 대화식 리베이스 편집 후 커밋 되돌리기를 수행 할 수 있음

나는 과거 커밋을 자주 수정하여 스크립트를 작성했습니다.

워크 플로우는 다음과 같습니다.

  1. git commit-edit <commit-hash>
    

    편집하려는 커밋에서 삭제됩니다.

  2. 커밋을 처음부터 원하는대로 수정하고 준비합니다.

    ( git stash save커밋하지 않은 파일을 유지하는 데 사용할 수 있습니다 )

  3. 다음과 같이 커밋을 다시 실행하십시오 --amend. 예 :

    git commit --amend
    
  4. 리베이스를 완료하십시오.

    git rebase --continue
    

위의 작업을 수행하려면 아래 스크립트를 다음의 실행 파일 git-commit-edit에 넣으십시오 $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

이 접근 방식으로 왔으며 (대화식 리베이스를 사용하는 것과 똑같을 수도 있습니다) 그러나 저에게는 간단합니다.

참고 : 나는 일상적인 대안 대신 할 수있는 일을 설명하기 위해이 접근법을 제시합니다. 그것은 많은 단계 (그리고 아마도 몇 가지주의 사항)가 있기 때문에.

커밋을 변경 0하고 현재 켜져 있다고 가정하십시오 .feature-branch

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

이 커밋을 확인하고을 만듭니다 quick-branch. 기능 분기를 복구 지점으로 시작하기 전에 복제 할 수도 있습니다 (시작하기 전에).

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

이제 다음과 같은 것을 갖게 될 것입니다 :

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

무대 변경, 다른 모든 것을 숨기십시오.

git add ./example.txt
git stash

변경 사항을 커밋하고 다시 체크 아웃 feature-branch

git commit --amend
git checkout feature-branch

이제 다음과 같은 것을 갖게 될 것입니다 :

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

REBASE feature-branch위에 quick-branch(길을 따라 충돌을 해결). 숨김을 적용하고 제거하십시오 quick-branch.

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

그리고 당신은 결국 :

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

Git은 rebasing 할 때 0 커밋을 복제하지 않습니다 (실제로 어느 정도 말할 수는 없지만).

참고 : 모든 커밋 해시는 원래 변경하려는 커밋부터 시작하여 변경됩니다.


6

비 대화식 명령을 얻으려면 PATH에 다음 내용의 스크립트를 넣으십시오.

#!/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"

을 사용하여 변경 사항을 준비한 다음 사용하여 git add실행하십시오 git fixup <commit-to-modify>. 물론, 충돌이 발생해도 여전히 대화식입니다.


1
이것은 잘 작동합니다. 커밋 세트를 완성하기 위해 더티 트리를 부분적으로 수정하는 기능을 추가했습니다. `dirtydiff = $ (git diff); if [ "$ {dirtydiff}"! = ""]; 그런 다음 "Stashing dirty tree"> & 2; 자식 숨김; fi;
Simon

6

git stash+ rebase자동화

Gerrit 리뷰를 위해 오래된 커밋을 여러 번 수정해야 할 때 다음과 같이했습니다.

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의 상류 .

용법:

  • 소스 파일을 수정하십시오. git add이미 repo 에 있을 필요는 없습니다.
  • git-amend-old $old_sha

나는 --autosquash다른 관련되지 않은 문제를 해결하지 않기 때문에 이것을 좋아합니다 .


아주 좋은 해결 방법 git amend은 현재 스 태쉬를 사용하여 특정 커밋에 변경 사항을 적용 하는 매우 기본적인 옵션입니다 .
caiohamamura

5

나는 이것을 해결했다.

1) 원하는 변경 사항으로 새 커밋을 생성하여 ..

r8gs4r commit 0

2) 어떤 커밋을 병합 해야하는지 알고 있습니다. 커밋 3입니다.

따라서 git rebase -i HEAD~4# 4는 최근 4 커밋을 나타냅니다 (커밋 3은 4 위입니다)

3) 대화 형 rebase에서 최근 커밋은 맨 아래에 있습니다. 비슷하게 보일 것입니다.

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

4) 특정 커밋과 병합하려면 커밋을 재 배열해야합니다. 그것은 같아야합니다

parent
|_child

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

다시 정렬 한 후에는 교체 할 필요가 p pickf( 픽스는 메시지를 커밋하지 않고 병합합니다) 또는 s( 스쿼시 커밋 메시지와 병합 런타임에 변경할 수 있습니다)

그런 다음 나무를 저장하십시오.

이제 기존 커밋과 병합이 완료되었습니다.

참고 : 스스로 관리하지 않는 한 바람직하지 않은 방법입니다. 팀 규모가 크면 자식 트리를 다시 쓸 수있는 방법이 아닌 다른 충돌을 일으 킵니다. 적은 커밋으로 트리를 깨끗하게 유지하려면이 시도를 할 수 있으며 작은 팀이 그렇지 않으면 바람직하지 않습니다 .....


대화식 리베이스 중에 라이브 수정을 원하지 않는 경우이 방법이 좋습니다.
Dunatotatos

4

가장 좋은 옵션은 "Interactive rebase command"를 사용하는 것 입니다.

git rebase명령은 엄청나게 강력합니다. 커밋 메시지 를 편집하고 커밋을 결합하고 순서를 바꿀 수 있습니다.

커밋을 리베이스 할 때마다 내용에 관계없이 커밋마다 새로운 SHA가 생성됩니다! 이 명령을 사용할 때는 특히 다른 개발자와 공동 작업 할 때이 명령에 중대한 영향을 줄 수 있으므로주의해야합니다. 당신이 일부를 rebasing하는 동안 그들은 커밋 작업을 시작할 수 있습니다. 커밋을 강제로 푸시하면 커밋이 동기화되지 않고 나중에 지저분한 상황에서 찾을 수 있습니다. 그러므로 조심 해주시길 바랍니다!

backup제어가 불가능한 것을 발견 할 때마다 이전 상태로 되돌아 갈 수 있도록 리베이스하기 전에 분기 를 만드는 것이 좋습니다 .

이제이 명령을 사용하는 방법은 무엇입니까?

git rebase -i <base> 

-i약자 "상호 작용" . 비 대화식 모드에서 리베이스를 수행 할 수 있습니다. 전의:

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

HEAD현재 위치를 나타냅니다 (지사 이름 또는 커밋 SHA 일 수도 있음). 그만큼~n수단 "N beforeé, 그래서 HEAD~n현재에있는 일 전에 N"커밋의 목록이 될 것입니다. "

git rebase 다음과 같은 다른 명령이 있습니다.

  • p 또는 pick 커밋을 그대로 유지합니다.
  • r 또는 reword : 커밋 내용을 유지하지만 커밋 메시지를 변경합니다.
  • s 또는 squash :이 커밋의 변경 사항을 이전 커밋 (목록에서 커밋 위의 커밋)으로 결합합니다.
  • ... 등

    참고 : Git을 코드 편집기와 함께 사용하여 작업을 단순화하는 것이 좋습니다. 예를 들어 비주얼 코드를 사용하는 경우 다음과 같이 추가 할 수 있습니다 git config --global core.editor "code --wait". 또는 원하는 코드 편집기를 GIT와 연결하는 방법을 Google에서 검색 할 수 있습니다.

의 예 git rebase

내가 한 마지막 2 커밋을 변경하고 싶었으므로 다음과 같이 처리하십시오.

  1. 현재 커밋을 표시합니다.
    #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. 이제 git rebase마지막 커밋 메시지 2 개를 변경하는 데 사용 합니다. $git rebase -i HEAD~2 코드 편집기를 열고 다음을 표시합니다.

    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
    ...
    

    이 2 개의 커밋에 대한 커밋 메시지를 변경하고 싶기 때문에. 그래서 r또는 reword대신 입력 pick합니다. 그런 다음 파일을 저장하고 탭을 닫으십시오. 참고 rebase다음 단계는 메시지를 업데이트하는 것입니다 수 있도록 여러 단계의 프로세스에서 실행됩니다. 또한 커밋은 역순으로 표시되므로 마지막 커밋은 해당 행에 표시되고 첫 번째 커밋은 첫 번째 행 등에 표시됩니다.

  3. 메시지 업데이트 : 첫 번째 메시지를 업데이트하십시오.

    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.
    ...
    

    저장 후 닫기 두 번째 메시지 편집

    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.
    ...
    

    저장하고 닫습니다.

  4. 리베이스가 끝날 때까지 이와 같은 메시지가 표시됩니다 Successfully rebased and updated refs/heads/documentation. 즉, 성공했음을 의미합니다. 변경 사항을 표시 할 수 있습니다.

    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
    

    나는 그것이 새로운 사용자에게 도움이되기를 바랍니다 :).


2

나를 위해 그것은 repo에서 일부 자격 증명을 제거하기위한 것이 었습니다. 나는 rebaseing을 시도하고 rebase를 계속하려고 할 때 관련이없는 것처럼 보이는 많은 갈등을 겪었습니다. 자신을 리베이스하려고 시도하지 말고 Mac에서 BFG (brew install bfg)라는 도구를 사용하십시오.


0

커밋을 아직 푸시하지 않은 경우 다음을 사용하여 이전 커밋으로 돌아갈 수 있습니다. git reset HEAD^[1,2,3,4...]

예를 들어

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

죄송합니다. 첫 번째 커밋에 file2를 추가하지 않았습니다 ...

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

git add <file2>

첫 번째 커밋에 file2가 추가됩니다.


0

글쎄,이 솔루션은 매우 어리석은 소리 일지 모르지만 특정 조건에서 당신을 구할 수 있습니다.

내 친구가 실수로 매우 큰 파일 (각각 3GB에서 5GB 사이의 4 개의 자동 생성 파일)을 커밋 한 후 git push더 이상 작동하지 않는 문제를 깨닫기 전에 그 위에 코드를 추가로 추가했습니다 !

파일이 나열 .gitignore되었지만 컨테이너 폴더 이름을 바꾼 후 노출되어 커밋되었습니다! 그리고 이제 그 위에 몇 가지 코드 커밋이 있었지만 push영원히 실행되고 (GB의 데이터를 업로드하려고 시도했습니다!) 마침내 Github의 파일 크기 제한 으로 인해 실패했습니다. .

대화식 리베이스 또는 이와 유사한 문제의 문제는 이러한 거대한 파일을 파고 다룰 때까지 계속해야한다는 것입니다. 그럼에도 불구하고 CLI에서 거의 한 시간을 보낸 후에 파일과 델타가 실제로 기록에서 제거되거나 현재 커밋에 포함되지 않았는지 확실하지 않았습니다. 푸시도 작동하지 않았고 친구가 실제로 붙어있었습니다.

그래서 내가 생각해 낸 해결책은 다음과 같습니다.

  1. 현재 자식 폴더의 이름을 ~/Project-old .
  2. github에서 git 폴더를 다시 복제하십시오. ~/Project ).
  3. 같은 지점으로 결제하십시오.
  4. 폴더 cp -r에서 파일을 수동 ~/Project-old으로~/Project .
  5. 체크인 할 필요가없는 대용량 파일이 mved에 포함되어 있는지 확인하십시오..gitignore 올바르게 있는지 확인하십시오.
  6. 또한 .git최근에 복제 된 폴더를 덮어 쓰지 않도록하십시오~/Project 한 . 그것이 문제의 역사의 통나무가 사는 곳입니다!
  7. 이제 변경 사항을 검토하십시오. 문제가있는 파일을 제외하고 모든 최근 커밋을 통합해야합니다.
  8. 마지막으로 변경 사항을 커밋하면 좋을 것 push입니다.

이 솔루션의 가장 큰 문제는 일부 파일을 수동으로 복사하고 최근의 모든 커밋을 하나로 병합하는 것입니다 (새 커밋 해시와 함께). B

가장 큰 이점은 모든 단계에서 매우 명확하고 대용량 파일 (민감한 파일)에 효과적 이며 역사에서 흔적을 남기지 않는다는 것입니다 !

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.