수정 된 커밋을 원격 Git 리포지토리에 어떻게 푸시합니까?


662

소스 코드로 약간 작업했을 때 평소 커밋을 한 다음 원격 저장소로 푸시했습니다. 그러나 소스 코드로 수입품을 정리하는 것을 잊어 버렸습니다. 따라서 이전 커밋을 대체하기 위해 amend 명령을 수행합니다.

> git commit --amend

불행히도 커밋을 리포지토리로 푸시 할 수 없습니다. 다음과 같이 거부됩니다.

> git push origin
To //my.remote.repo.com/stuff.git/
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to '//my.remote.repo.com/stuff.git/'

어떻게해야합니까? (원격 저장소에 액세스 할 수 있습니다.)


내 --amend이 커밋 메시지 만 변경하면 어떻게됩니까? 마지막 커밋 메시지가 이미 원격으로 푸시 된 경우 편집하는 방법은 무엇입니까? 나는 Github에서 그것을했고 비 빨리 감기에 관한 동일한 메시지를 받았다. 그런 다음 아래에 솔루션을 적용했지만 병합은 맨 위에 더 많은 커밋 메시지를 추가했습니다.

7
@ faB : 나는 이것이 FAQ라고 생각합니다. 확약 메시지가 너무 chaning, 커밋 함께 해싱 revid (해시)를 변경한다. 명확하지 않은 경우 : 아니요. IIRC는 대역 외 정보를 메모에 저장할 수 있습니다 (따라서 기존 커밋을 변경하지 않고도 주석을 달 수 있습니다). 특정 커밋에 레이블을 지정하려면 태그를 사용하십시오
sehe

1
곧 (git1.8.5는, Q4 2013) 할 수 DO가 git push -force주의 깊게 더 .
VonC

3
카우보이 스타일입니다. 더 이상 배우지 않거나 이전 git amend을 취소하는 방법을 찾지 마십시오. 그냥 자리 표시 자 코드를 추가하십시오. 주석을 추가하고 코드를 정리하거나 대시 대시를 몇 개만 추가하면됩니다. 이제 실제 커밋을 만들어 원격으로 보냅니다. 완료!
nehem

@ user58777 -amend가 커밋 메시지 만 변경하고 그 이후로 로컬 커밋을 추가하지 않은 경우 커밋 메시지를 수정하기 전에 푸시 한 원격 커밋으로 로컬 분기를 재설정 할 수 있습니다.
Scott Ahten

답변:


504

사실 한 번에 밀어 --force.git저장소와 리누스 꾸중있어 BIG TIME . 일반적으로 이것은 다른 사람들에게 많은 문제를 일으킬 것입니다. 간단한 답변은 "하지 마십시오"입니다.

나는 다른 사람들이 어쨌든 그렇게하는 요리법을 보았으므로 여기서는 반복하지 않을 것입니다. 그러나 다음은 --force (또는 + master)로 수정 된 커밋을 푸시 한 후 상황을 복구하기위한 팁 입니다.

  1. git reflog수정 한 이전 커밋을 찾는 데 사용 합니다 (호출하면을 수정 old하여 새로 만든 커밋을 호출합니다 new).
  2. old와 같은 new트리를 기록하여 와 사이에 병합을 만듭니다 .newgit checkout new && git merge -s ours old
  3. 이것을 마스터에게 병합 git merge master
  4. 결과로 마스터를 업데이트하십시오. git push . HEAD:master
  5. 결과를 밀어 내십시오.

를 사용해서 개정하고 결과 병합 당신이 선호하는 것을 볼 수 있습니다 볼 수 푸시를 강제로 말소 커밋에 그런 불행한 충분히 있었다 사람들은 자신의 작품을 기반으로 한하는 new동안 old. 그들의 나중에 병합이 사이의 충돌이 표시되지 않습니다 old그리고 new그들이 고통을하지 않아도, 당신의 개정으로 인한 것을.


17
나는 역사를 파괴함으로써 수정 된 커밋을 강요 할 때 어떤 일이 발생하는지 잘 알고있다. 운 좋게도, 나는 원격 저장소가 네트워크 드라이브에있는 프로젝트의 유일한 개발자 였기 때문에 그렇게 큰 문제는 아니 었습니다. 나는 수정 커밋을 병합하는 것에 대해 생각하지 않았으므로 이것을 찬성합니다.
Spoike

61
우리 회사에서는 개인이 개발 한 피처 브랜치를 매우 정기적으로 강제 푸시합니다.
Ondra Žižka

2
Linus의 꾸짖음은 강제 옵션을 사용하여 기록을 삭제했기 때문이 아니라 수행하지 않아야하기 때문입니다. GabrielleV의 솔루션은 역사를 바꾸지 않기 때문에 잘 작동합니다.
user411279

2
이 답변의 저자 (gitster)는 더 이상 존재하지 않는 것 같으므로 누구나 항목 번호 1을 명확히하는 데 도움이 될 수 있습니다. 오래된 커밋을 찾으십시오. 백업이 없으면 어디서 찾을 수 있습니까? 수정과 강제 추진은 파괴되지 않았을까? 어쩌면 그는 여전히 나무에 그것을 가지고있는 친구 / 협력자로부터 그것을 얻는 것을 언급하고 있습니까?
Dr Beco

2
박사 Breco 당신은 git reflog그것을 찾을 수 있습니다
Simon Zyx

269

Git 안전 기능이 보입니다. Git은 브랜치로 원격 브랜치를 업데이트하지 않습니다. 브랜치의 헤드 커밋은 푸시하려는 브랜치의 현재 헤드 커밋의 직접적인 후손이 아니기 때문입니다.

이것이 사실이 아니라면, 거의 같은 시간에 같은 저장소로 밀고있는 두 사람은 동시에 새로운 커밋이 들어 왔으며 마지막으로 밀린 사람은 이전 푸셔의 작업을 그들은 이것을 깨달았습니다.

당신이 밀고있는 유일한 사람이라는 것을 알고 있고 수정 된 커밋을 푸시하거나 브랜치를 되 돌리는 커밋을 푸시하려는 경우, -f스위치 를 사용하여 Git이 원격 브랜치를 업데이트하도록 '강제'할 수 있습니다 .

git push -f origin master

원격 저장소가 구성 변수를 사용하여 맨 끝에서 비 빨리 푸시를 거부 할 수 있기 때문에 Git이 작동하지 않을 수도 있습니다 receive.denynonfastforwards. 이 경우 거부 사유는 다음과 같습니다 ( '원격 거부 됨'부분 참고).

 ! [remote rejected] master -> master (non-fast forward)

이 문제를 해결하려면 원격 저장소의 구성을 변경하거나 더티 해킹으로 분기를 삭제하고 다시 만들 수 있습니다.

git push origin :master
git push origin master

일반적으로 마지막 매개 변수 git push는 형식 을 사용합니다 <local_ref>:<remote_ref>. 여기서 local_ref로컬 저장소 remote_ref의 분기 이름이고 원격 저장소의 분기 이름입니다. 이 명령 쌍은 두 개의 속기를 사용합니다. :masternull local_ref는 null 분기를 원격 측으로 푸시하는 것을 의미 master합니다. 즉, 원격 분기를 삭제합니다. 없는 지점 이름 :은 지정된 이름의 로컬 지점을 동일한 이름의 원격 지점으로 푸시합니다. master이 상황에서는 짧습니다 master:master.


2
이것은 github에서 작동하지 않았으며 다음 메시지를 표시했습니다. [원격 거부 됨] master (현재 지점 삭제 금지)
vedang

나는 푸시 (강제로 문제를 해결할 것이라고 알고 있음)를 강요하고 싶지 않았지만 이제는 선택의 여지가 없다고 생각합니다.
vedang

1
이것은 assembla로 호스팅 된 내 repo에서 작동하는 유일한 솔루션입니다.
저스틴

1
원격 마스터 브랜치를 삭제하면 원격 저장소의 공간이 비워 집니까?
Mr_and_Mrs_D

1
@Mr_and_Mrs_D : 즉시는 아니지만 한 git gc번 후 reflogs가 만료되면 오래된 객체가 제거됩니다. 저장소를 복제하는 사람은 분기가 업데이트 되 자마자 더 이상 도달 할 수없는 객체를 얻지 못합니다.
CB Bailey

211

빠른 답변 : 여기에 간단한 답변을 게시 한 사람이 아무도 없다는 사실은 Git CLI가 보여주는 절박한 사용자 적대감을 보여줍니다.

어쨌든, 당신이 강요를 시도하지 않았다고 가정 할 때, 이것을하는 "명백한"방법은 먼저 당기는 것입니다. 이렇게하면 수정 한 (그리고 더 이상 가지고 있지 않은) 변경 사항이 다시 적용됩니다.

충돌이 해결되면 다시 푸시 할 수 있습니다.

그래서:

git pull

풀 오류가 발생하면 로컬 리포지토리 구성에 문제가있을 수 있습니다 (.git / config 분기 섹션에 잘못된 참조가 있음).

그리고 후에

git push

어쩌면 "Trivial merge"에 대해 주제와 추가 커밋을받을 수도 있습니다.


2
예, 이것에 대해 썼습니다 . stackoverflow.com/questions/253055/… ;)
Spoike

10
예상대로 작동하지 않습니다. 두 개의 새로운 커밋을 만듭니다. 하나는 이전 것의 복제품이지만 수정 된 변경 사항이 있습니다. 그리고 하나의 병합 커밋은 빈 diff로 이루어집니다. 여전히 오래된 커밋을 변경하지 않고 수정하려고했던 민감한 데이터가 드러났습니다. 저는 믿습니다 git push -f또는 git reset여기에 갈 수있는 유일한 방법입니다.
thnee

40
기술적으로 문제에 대답하지만 실제로 문제를 해결하지는 않습니다. 당신이 말했듯이, 추가 커밋을 생성하지만 사람들이 커밋을 수정하는 주된 이유는 새로운 커밋을 생성하지 않기 위해서입니다. 포스터가 당신의 지시를 따른다면, 원하는 결과를 얻지 못할 것입니다. 처음에는 커밋을 수정하지 않는 것이 좋습니다.
Dan Jones

102

짧은 대답 : 수정 된 커밋을 공개 리포지토리로 푸시하지 마십시오.

긴 대답 : git commit --amendand 같은 몇몇 Git 명령 git rebase은 실제로 히스토리 그래프를 다시 작성합니다. 변경 사항을 게시하지 않는 한 괜찮습니다. 일단 변경하면 누군가가 이미 변경 사항을 가져 와서 다시 가져 오면 실패 할 수 있기 때문에 실제로 역사와 관련해서는 안됩니다. . 커밋을 수정하는 대신 변경 사항을 적용하여 새로 커밋해야합니다.

그러나 실제로 수정 된 커밋을 푸시하려면 다음과 같이하십시오.

$ git push origin +master:master

선행 +부호는 "빨리 감기"커밋이 발생하지 않더라도 푸시가 발생하도록합니다. 추진중인 변경 사항이 이미 공개 리포지토리에있는 변경 사항 의 직접적인 후손 인 경우 빨리 감기 커밋이 발생합니다 .


5
이것은 git push -f와 어떻게 다릅니 까? 감사!
bentford

11
@ bentford : 기본적으로와 같은 것 git push -f입니다.
mipadi

54

다음은 이미 작성한 후 변경 사항을 푸시하는 매우 간단하고 깨끗한 방법입니다 commit --amend.

git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master

다음은 무엇입니까?

  • 분기 헤드를 상위 커밋으로 재설정합니다.
  • 이 마지막 커밋을 보관하십시오.
  • 원격으로 강제 푸시합니다. 이제 원격에 마지막 커밋이 없습니다.
  • 당신의 숨결을 터 뜨리십시오.
  • 깨끗하게 커밋하십시오.
  • 리모콘으로 미십시오.

다른 지점이나 원격지에 적용 할 경우 "origin"과 "master"를 변경해야합니다.


3
2 비고 :-다른 지사에서 작업하는 경우 지사 이름을 git add변경하십시오. 변경 사항을 포함하기 위해 커밋하기 전에 사용해야했습니다 .
SylvainB

1
Windows CMD에서 첫 번째 명령은 이스케이프되어야합니다 git reset --soft "HEAD^". 나머지는 잘 작동합니다.
MrMister

2
"매우 간단하고 깨끗한 방법 .."cit. 이 절차에는 강제 푸시가 포함됩니다. 위의 답변에서 모든 비판에 비추어 볼 때 나는이 절차가 실제로 깨끗한 것인지 확실하지 않습니다.
Na13-c

24

로컬 수정 커밋을 버리고 새로운 변경 사항을 맨 위에 추가하여 문제를 해결했습니다.

# Rewind to commit before conflicting
git reset --soft HEAD~1

# Pull the remote version
git pull

# Add the new commit on top
git add ...
git commit
git push

2
이것은 가장 간단한 버전입니다!
mknaf

기록을 다시 작성하는 것보다 다른 '변경'커밋을 추가하는 것이 좋습니다. @mknaf에 동의합니다
sdkks

8

나는 같은 문제가 있었다.

  • 이미 푸시 된 마지막 커밋을 실수로 수정했습니다.
  • 로컬에서 많은 변경을 수행하고 약 5 번 커밋
  • 푸시 시도, 오류, 당황, 원격 병합, 많은 내 파일이 없음, 푸시, 실패 등

Git 초보자 인 나는 그것이 완전한 FUBAR 라고 생각했다 .

솔루션 : @bara가 제안한 + 로컬 백업 분기 생성

# Rewind to commit just before the pushed-and-amended one.
# Replace <hash> with the needed hash.
# --soft means: leave all the changes there, so nothing is lost.
git reset --soft <hash>

# Create new branch, just for a backup, still having all changes in it.
# The branch was feature/1234, new one - feature/1234-gone-bad
git checkout -b feature/1234-gone-bad

# Commit all the changes (all the mess) not to lose it & not to carry around
git commit -a -m "feature/1234 backup"

# Switch back to the original branch
git checkout feature/1234

# Pull the from remote (named 'origin'), thus 'repairing' our main problem
git pull origin/feature/1234

# Now you have a clean-and-non-diverged branch and a backup of the local changes.
# Check the needed files from the backup branch
git checkout feature/1234-gone-bad -- the/path/to/file.php

어쩌면 그것은 빠르고 깨끗한 해결책이 아니며 내 역사 (5 대신 1 커밋)를 잃어 버렸지 만 하루의 작업을 절약했습니다.


6

코드를 원격 브랜치 (GitHub / Bitbucket)로 푸시하지 않은 경우 다음과 같이 명령 행에서 커밋 메시지를 변경할 수 있습니다.

 git commit --amend -m "Your new message"

특정 지점에서 작업하는 경우 다음을 수행하십시오.

git commit --amend -m "BRANCH-NAME: new message"

이미 잘못된 메시지로 코드를 푸시 한 경우 메시지를 변경할 때주의해야합니다. 즉, 커밋 메시지를 변경하고 다시 밀어 넣으면 문제가 발생합니다. 부드럽게하려면 다음 단계를 수행하십시오.

하기 전에 전체 답변을 읽으십시오

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

중요 사항 : 강제 푸시를 직접 사용하면 다른 개발자가 동일한 브랜치에서 작업하는 코드 문제가 발생할 수 있습니다. 따라서 이러한 충돌을 피하려면 강제 푸시를 수행 하기 전에 지점에서 코드를 가져와야합니다 .

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

커밋 메시지가 이미 푸시 된 경우이를 변경하는 것이 가장 좋습니다.


1
마지막 예제에서 커밋을 성공적으로 철회했다면 왜 강제로 푸시해야합니까? 표준 푸시 충분하지 않습니까? 감사합니다
Thomas

토마스가 묻는 질문은 실제로 매우 유효합니다. 나 자신은 풀을 따라 밀어 넣을 필요가 없었습니다.
Na13-c

해결 방법이 있기 때문에 "모범 사례"라고 부르지 마십시오 --force. 허용 된 답변보기
Farid

5

아무도 수정하지 않은 커밋을 가져 오지 않았다면의 --force-with-lease옵션을 사용하십시오 git push.

TortoiseGit에서 "푸시 ..."옵션 "강제 : 무시할 수 있음"및 "알려진 변경 사항 확인"에서 동일한 작업을 수행 할 수 있습니다.

Force (알려진 변경 내용을 버릴 수 있음 )를 사용하면 원격 저장소가보다 안전한 앞으로 빨리 밀기를 허용 할 수 있습니다. 이로 인해 원격 저장소가 커밋을 잃을 수 있습니다. 조심해서 사용하십시오. 이렇게하면 리모콘에있는 다른 사람의 알 수없는 변경 사항이 손실되지 않습니다. 서버 분기가 원격 추적 분기와 동일한 커밋을 가리키는 지 확인합니다 (알려진 변경 사항). 그렇다면, 강제 푸시가 수행됩니다. 그렇지 않으면 거부됩니다. git에는 원격 추적 태그가 없으므로이 옵션을 사용하여 태그를 덮어 쓸 수 없습니다.


4

Git 리모컨에 이미 커밋 파일이 있기 때문에이 오류가 발생합니다. 이것이 작동하려면 지점을 강제로 밀어야합니다.

git push -f origin branch_name

또한 팀의 다른 사람이 동일한 지점으로 푸시했을 수 있으므로 원격에서 코드를 가져와야합니다.

git pull origin branch_name

이것은 커밋을 원격으로 강제 푸시 해야하는 경우 중 하나입니다.


이 답변이 이전 답변에서 제기 된 주요 의견을 설명하지 않는 이유는 무엇입니까?
Na13-c

2

다음 git add "your files"git commit --amend같이 이미 변경 한 후 변경 사항을 적용 할 수있는 매우 간단하고 깨끗한 방법입니다 .

git push origin master -f

또는:

git push origin master --force

나는 그것이 나쁘다는 것을 듣고 확신합니다. git이 기본적으로 실패하고 (--force가 필요함) 이유가 있습니다.
Rolf

1

원격 리포지토리에서 가져 와서 발생하고 커밋 한 다음 푸시하는 병합 충돌을 처리 하여이 문제를 해결해야했습니다. 그러나 더 좋은 방법이 있다고 생각합니다.


실제로는 아닙니다. 원격 저장소에서 로컬 사본을 업데이트하지 않았기 때문일 수 있습니다. Git은 수동으로 병합을 처리해야 할 수도 있으므로 푸시하지 않습니다. 다른 답변에는 푸시 명령을 내리는 명령 (및 설명)이 있지만 리모콘의 변경 사항을 삭제할 수 있습니다.
mipadi

1

나는 단지 Git이 말한 것을 계속했다. 그래서:

  • 수정 된 커밋으로 인해 푸시 할 수 없습니다.
  • 나는 제안대로 당겨.
  • 병합이 실패합니다. 수동으로 수정합니다.
  • 새 커밋 ( "병합"으로 레이블이 지정됨)을 작성하고 푸시하십시오.
  • 작동하는 것 같습니다!

참고 : 수정 된 커밋은 최신 커밋입니다.


1
평판이 더 높으면 공감할 것이므로 여기서 정중하게 물어 보자. 수정 한 사람? 수정 된 커밋을 가진 지점에서 당기고 일했던 사람? 수정 전이나 후에? 난 당신을 오해했기 때문에 내 모든 수정을 취소했습니다 ... 다행히도별로 없었습니다 ...
Bartis Áron

1

커밋의 작성자 및 커미터를 변경할 때 다음이 도움이되었습니다.

git push -f origin master

Git은 메타 정보 섹션에서만 다른 동일한 델타의 커밋임을 알아낼 정도로 똑똑했습니다.

로컬 헤드와 원격 헤드 모두 해당 커밋을 가리 켰습니다.



0

다음은 이전 커밋에서 편집을 수정 한 방법입니다.

  1. 지금까지 작업을 저장하십시오.
  2. 작성된 경우 변경 사항을 보관하십시오. git stash이제 작업 사본이 마지막 커밋 상태에서 깨끗합니다.
  3. 수정하고 수정하십시오.
  4. "수정" 모드 에서 변경 사항을 커밋하십시오 .git commit --all --amend
  5. 편집기에서 로그 메시지 (기본적으로 이전 로그 메시지)를 요청합니다. 편집기가 마음에 들면 저장하고 종료하십시오.

    새로운 변경 사항이 이전 커밋에 추가됩니다. 와 자신에 대한 참조 git loggit diff HEAD^

  6. 작성된 변경 사항을 다시 적용하십시오. git stash apply

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