首页 > 解决方案 > 由于日期更改的错误变基而删除未推送的重复 git 提交?

问题描述

我一直在尝试修改未推送提交的时间戳,并且犯了一个错误(做了一个新的分支并合并,而不是 rebase --continue),导致尚未推送的提交重复。这是一个模拟问题的 bash 脚本,例如test.sh

rm -rf mytestgit
mkdir mytestgit
cd mytestgit
git init
git config user.email "you@example.com"
git config user.name "Your Name"

SLEEPTIME=5

git commit --allow-empty -m 'first commit'
echo " (... wait ...) "; sleep $SLEEPTIME
git commit --allow-empty -m 'second commit'
echo " (... wait ...) "; sleep $SLEEPTIME
THIRDC=$(git commit --allow-empty -m 'third commit')
echo $THIRDC
echo " (... wait ...) "; sleep $SLEEPTIME
git commit --allow-empty -m 'fourth commit'

git status

git --no-pager log --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d" ; echo # add '\n' at end
GLOGLAST=$(git --no-pager log -1 --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d")
IFS=+ read left SPLITGLLA <<< "$GLOGLAST"
IFS="   " read SPLITGLL right  <<< "$SPLITGLLA" # this is TAB here, not space, for IFS
TIMEZONE=${SPLITGLL[0]}
SPLITTC=(${THIRDC//]/ })
THIRDCHASH="${SPLITTC[1]}"
THIRDCUTS=$(git show -s --format=%ct $THIRDCHASH)
THIRDCUTSNEW=$((THIRDCUTS-3))
echo "Third commit hash: $THIRDCHASH, Unix timestamp $THIRDCUTS, timezone +$TIMEZONE, new Unix timestamp (three seconds earlier) $THIRDCUTSNEW"
echo

# cd mytestgit # already in
# here choose $THIRDCHASH with e, saving and closing text editor
git rebase $THIRDCHASH^ -i --keep-empty
GIT_COMMITTER_DATE="$THIRDCUTSNEW +$TIMEZONE" git commit --amend --no-edit --allow-empty --date "$THIRDCUTSNEW +$TIMEZONE"

# here the mistake
git checkout -b newbranch
git checkout master
git merge newbranch
git branch -d newbranch

# check final state
git --no-pager log --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d" ; echo # add '\n' at end

当我运行这个脚本时,我得到,说这个输出:

Initialized empty Git repository in /tmp/mytestgit/.git/
[master (root-commit) 1a5fa9a] first commit
 (... wait ...) 
[master f6b51cc] second commit
 (... wait ...) 
[master f9871cc] third commit
 (... wait ...) 
[master cfd0208] fourth commit
On branch master
nothing to commit, working directory clean
* cfd0208   Your Name   Tue Oct 2 13:05:00 2018 +0200   fourth commit  (HEAD, master)
* f9871cc   Your Name   Tue Oct 2 13:04:55 2018 +0200   third commit 
* f6b51cc   Your Name   Tue Oct 2 13:04:50 2018 +0200   second commit 
* 1a5fa9a   Your Name   Tue Oct 2 13:04:45 2018 +0200   first commit 
Third commit hash: f9871cc, Unix timestamp 1538478295, timezone +0200, new Unix timestamp (three seconds earlier) 1538478292

Stopped at f9871cca92f2e3da587fa8b16021f8e52976c8d9... third commit
You can amend the commit now, with

    git commit --amend

Once you are satisfied with your changes, run

    git rebase --continue

...然后在变基处,我在自动启动的文本编辑器中有这个(将第一个更改picke):

e f9871cc third commit
pick cfd0208 fourth commit

# Rebase f6b51cc..cfd0208 onto f6b51cc
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#

...我保存,然后退出文本编辑器 - 脚本继续:

[detached HEAD 63e35fe] third commit
Switched to a new branch 'newbranch'
Switched to branch 'master'

...并且在错误的合并中,我在自动启动的文本编辑器中得到了这个:

Merge branch 'newbranch'

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

...我保存而不做任何更改,然后退出文本编辑器 - 脚本以显示最终状态结束:

Already up-to-date!
Merge made by the 'recursive' strategy.
Deleted branch newbranch (was 63e35fe).
*   9b1ac28 Your Name   Tue Oct 2 13:05:36 2018 +0200   Merge branch 'newbranch'  (HEAD, master)
|\  
| * 63e35fe Your Name   Tue Oct 2 13:04:52 2018 +0200   third commit 
* | cfd0208 Your Name   Tue Oct 2 13:05:00 2018 +0200   fourth commit 
* | f9871cc Your Name   Tue Oct 2 13:04:55 2018 +0200   third commit 
|/  
* f6b51cc   Your Name   Tue Oct 2 13:04:50 2018 +0200   second commit 
* 1a5fa9a   Your Name   Tue Oct 2 13:04:45 2018 +0200   first commit 

所以,现在我有重复的提交(63e35fe“第三次提交”),以及一个合并提交(9b1ac28“合并分支'newbranch'”)而不是重复的“第四次提交”。

基本上,我已经将第二次和第一次提交推送到在线回购,但第三次和第四次还没有被推送。

如何删除重复的(63e35fe“第三次提交”,这是以更改的时间戳结束的那个,而不是原始的 f9871cc“第三次提交”)和额外的合并(9b1ac28“合并分支'newbranch'”)提交所以我最终不会将它们推向回购吗?

或者换句话说,我怎样才能将 repo 的状态恢复到git rebase $THIRDCHASH^ -i --keep-empty命令运行之前 - 所以我可以再次重新运行它,并正确地用git rebase --continue而不是合并来结束它,所以我可以推送“原始”提交(而不是重复/附加)在线?

标签: git

解决方案


事实证明,在 OP 结束的状态下,还有一个 rebase-merge 目录:

$ git rebase f6b51cc^ -i --keep-empty

It seems that there is already a rebase-merge directory, and
I wonder if you are in the middle of another rebase.  If that is the
case, please try
    git rebase (--continue | --abort | --skip)
If that is not the case, please
    rm -fr "/tmp/mytestgit/.git/rebase-merge"
and run me again.  I am stopping in case you still have something
valuable there.

...我已经完成但忘记提及的另一个步骤是:

rm -fr "/tmp/mytestgit/.git/rebase-merge"

...然后结果如下图:

$ git --no-pager log --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d" ; echo
* 93bf274   Your Name   Tue Oct 2 13:05:00 2018 +0200   fourth commit  (HEAD, master)
*   9b1ac28 Your Name   Tue Oct 2 13:05:36 2018 +0200   Merge branch 'newbranch' 
|\  
| * 63e35fe Your Name   Tue Oct 2 13:04:52 2018 +0200   third commit 
* | cfd0208 Your Name   Tue Oct 2 13:05:00 2018 +0200   fourth commit 
* | f9871cc Your Name   Tue Oct 2 13:04:55 2018 +0200   third commit 
|/  
* f6b51cc   Your Name   Tue Oct 2 13:04:50 2018 +0200   second commit 
* 1a5fa9a   Your Name   Tue Oct 2 13:04:45 2018 +0200   first commit 

然后,我做git rebase f6b51cc^ -i --keep-empty了:

pick f6b51cc second commit
pick f9871cc third commit
pick cfd0208 fourth commit
#pick 63e35fe third commit
#pick 93bf274 fourth commit

# Rebase 1a5fa9a..93bf274 onto 1a5fa9a
#
# Commands:
...

...这样 63e35fe 和 93bf274 被删除(注意 9b1ac28 "Merge branch 'newbranch'" 不在给定列表中),我得到结果:

Successfully rebased and updated refs/heads/master.

...这里的状态是:

$ git --no-pager log --graph --abbrev-commit --all --decorate --pretty=format:"%h%x09%an%x09%ad%x09%s %d" ; echo
* cfd0208   Your Name   Tue Oct 2 13:05:00 2018 +0200   fourth commit  (HEAD, master)
* f9871cc   Your Name   Tue Oct 2 13:04:55 2018 +0200   third commit 
* f6b51cc   Your Name   Tue Oct 2 13:04:50 2018 +0200   second commit 
* 1a5fa9a   Your Name   Tue Oct 2 13:04:45 2018 +0200   first commit 

...这是第一次变基之前的状态(应该已经改变了时间戳)——这就是我想要的。


推荐阅读