git - 由于日期更改的错误变基而删除未推送的重复 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
...然后在变基处,我在自动启动的文本编辑器中有这个(将第一个更改pick
为e
):
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
而不是合并来结束它,所以我可以推送“原始”提交(而不是重复/附加)在线?
解决方案
事实证明,在 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
...这是第一次变基之前的状态(应该已经改变了时间戳)——这就是我想要的。
推荐阅读
- javascript - Vue数据价值生命周期
- c# - Xamarin.Forms 应用上的 Android 的 Firebase 初始化失败
- outlook - 单击即可自动将电子邮件移动到垃圾箱?
- r - 关于跨列公共值的问题
- macos - 无法在 Mac OS X Mojave 上重新启动 Apache 2
- arrays - 将粗体句子之间的所有信息存储为数组元素,Word VBA
- c - 在 C 中使用 Switch 向数组添加字符
- mysql - mysql函数将分钟转换为月、日、小时、分钟和秒值
- css - 在 ReactJS 中使用过渡淡化元素
- aws-lambda - 如何配置 AWS API Gateway HTTP GET 以将 BASE64 字符串作为二进制数据返回?