我该如何拆分历史记录中的Git提交?

本文翻译自:How can I split up a Git commit buried in history?

I flubbed up my history and want to do some changes to it. 我摸索了自己的历史,并希望对其进行一些更改。 Problem is, I have a commit with two unrelated changes, and this commit is surrounded by some other changes in my local (non-pushed) history. 问题是,我的提交具有两个不相关的更改,并且此提交被我的本地(非推送)历史记录中的其他一些更改所围绕。

I want to split up this commit before I push it out, but most of the guides I'm seeing have to do with splitting up your most recent commit, or uncommitted local changes. 我想在提交之前拆分此提交,但是我看到的大多数指南都与拆分最近的提交或未提交的本地更改有关。 Is it feasible to do this to a commit that is buried in history a bit, without having to "re-do" my commits since then? 这样做对埋在历史中的某个提交进行此操作是否可行,而此后不必“重做”我的提交呢?


#1楼

参考:https://stackoom.com/question/i4th/我该如何拆分历史记录中的Git提交


#2楼

If you haven't pushed yet, just use git rebase . 如果尚未推送,请使用git rebase Even better, use git rebase -i to move commits around interactively. 更好的是,使用git rebase -i交互移动提交。 You can move the offending commit to the front, then split it up as you like and move the patches back (if needed). 您可以将有问题的提交移到最前面,然后根据需要将其拆分,然后将补丁移回(如果需要)。


#3楼

There is a guide to splitting commits in the rebase manpage . 在rebase联机帮助页中有一个拆分提交的指南。 The quick summary is: 快速摘要是:

  • Perform an interactive rebase including the target commit (eg git rebase -i <commit-to-split>^ branch ) and mark it to be edited. 执行包含目标提交的交互式rebase(例如git rebase -i <commit-to-split>^ branch )并将其标记为要编辑。

  • When the rebase reaches that commit, use git reset HEAD^ to reset to before the commit, but keep your work tree intact. 当rebase到达该提交时,请使用git reset HEAD^复位到提交之前,但请保持工作树完整。

  • Incrementally add changes and commit them, making as many commits as desired. 增量添加更改并提交,并根据需要进行任意数量的提交。 add -p can be useful to add only some of the changes in a given file. add -p在仅添加给定文件中的某些更改时很有用。 Use commit -c ORIG_HEAD if you want to re-use the original commit message for a certain commit. 如果要对某个提交重复使用原始提交消息,请使用commit -c ORIG_HEAD

  • If you want to test what you're committing (good idea!) use git stash to hide away the part you haven't committed (or stash --keep-index before you even commit it), test, then git stash pop to return the rest to the work tree. 如果您想测试要提交的内容(好主意!),请使用git stash隐藏未提交的部分(或在提交之前隐藏stash --keep-index ),然后进行测试,然后git stash pop to将其余的工作返还给工作树。 Keep making commits until you get all modifications committed, ie have a clean work tree. 继续进行提交,直到完成所有修改为止,即拥有干净的工作树。

  • Run git rebase --continue to proceed applying the commits after the now-split commit. 运行git rebase --continue ,在现在拆分的提交之后继续应用提交。


#4楼

To split a commit <commit> and add the new commit before this one , and save the author date of <commit> , — the steps are following: 要拆分提交<commit>在此提交之前添加新的提交 ,并保存<commit>的作者日期,请<commit>以下步骤:

  1. Edit the commit before <commit> <commit> 之前编辑<commit>

     git rebase -i <commit>^^ 

    NB: perhaps it will be also needed to edit <commit> as well. 注意:也许还需要编辑<commit>

  2. Cherry pick <commit> into the index 樱桃选择<commit>进入索引

     git cherry-pick -n <commit> 
  3. Interactively reset unneeded changes from the index and reset the working tree 交互地重置索引中不需要的更改并重置工作树

     git reset -p && git checkout-index -f -a 

    As alternative, just stash unneeded changes interactively: git stash push -p -m "tmp other changes" 另外,也可以交互地隐藏不需要的更改: git stash push -p -m "tmp other changes"

  4. Make other changes (if any) and create the new commit 进行其他更改(如果有)并创建新的提交

     git commit -m "upd something" . 

    Optionally, repeat the items 2-4 to add more intermediate commits. (可选)重复项目2-4以添加更多中间提交。

  5. Continue rebasing 继续重新定基

     git rebase --continue 

#5楼

Here's how to do it with Magit . 这是使用Magit的方法

Say commit ed417ae is the one you want to change; 假设ed417ae是您要更改的; it contains two unrelated changes and is buried under one or more commits. 它包含两个不相关的更改,并被隐藏在一个或多个提交中。 Hit ll to show the log, and navigate to ed417ae: 点击ll以显示日志,并导航到ed417ae:

初始日志

Then hit r to open the rebase popup 然后按r打开变基弹出窗口

重新设置弹出窗口

and m to modify the commit at point. m修改点的提交。

Notice how the @ there is now on the commit you want to split – that means HEAD is now at that commit: 请注意,现在要拆分的提交上的@是什么–这意味着HEAD现在位于该提交上:

修改提交

We want to move HEAD to the parent, so navigate to the parent (47e18b3) and hit x ( magit-reset-quickly , bound to o if you're using evil-magit ) and enter to say "yes I meant commit at point". 我们想将HEAD移至父级,因此导航至父级(47e18b3),然后按xmagit-reset-quickly ,如果您使用evil-magit ,则绑定到o ),然后输入“是的,我的意思是在点提交”。 Your log should now look like: 您的日志现在应如下所示:

重置后记录

Now, hit q to go to the regular Magit status, then use the regular unstage u command to unstage what doesn't go in the first commit, commit c the rest as usual, then s tage and c ommit what goes in the second commit, and when done: hit r to open the rebase popup 现在,命中q去正规Magit状态,然后使用常规的unstage u命令unstage什么不会在第一次提交去,提交c其余像往常一样,然后s踏歌和c ommit在第二次提交发生的事情,并在完成后:按r打开重新设置弹出窗口

重新设置弹出窗口

and another r to continue, and you're done! 另一个r继续,就完成了! ll now shows: ll现在显示:

全部完成日志


#6楼

There's a faster version if you only want to extract content from just one file. 如果您只想从一个文件中提取内容,则有一个更快的版本。 It's faster because the interactive rebase is not actually interactive anymore (and it's of course even faster if you want to extract from the last commit, then no need to rebase at all) 之所以更快,是因为交互式变基实际上不再是交互式的了(如果您想从上一次提交中提取内容,那么它甚至更快,那么根本就不需要变基)

  1. Use your editor and delete the lines you want to extract from the_file . 使用编辑器并删除要从the_file提取的the_file Close the_file . 关闭the_file That's the only edition you need, all the rest is just git commands. 那是您唯一需要的版本,其余的只是git命令。
  2. Stage that deletion in the index: 在索引中进行该删除:

     git add the_file 
  3. Restore the lines you just deleted back into the file without affecting the index ! 将刚删除的行恢复到文件中, 而不会影响索引

     git show HEAD:./the_file > the_file 
  4. "SHA1" is the commit you want to extract the lines from: “ SHA1”是您要从中提取行的提交:

     git commit -m 'fixup! SHA1' 
  5. Create the second, brand new commit with the content to extract restored by step 3: 创建第二个全新提交,其内容要提取到步骤3中还原的内容:

     git commit -m 'second and new commit' the_file 
  6. Don't edit, don't stop/continue - just accept everything: 不要编辑,不要停止/继续-只接受所有内容:

     git rebase --autosquash -i SHA1~1 

Of course even faster when the commit to extract from is the last commit: 当然,如果要提取的提交是最后的提交,则速度更快:

4. git commit -C HEAD --amend
5. git commit -m 'second and new commit' thefile
6. no rebase, nothing

If you use magit then step 4, 5 and 6 are a single action: Commit, instant Fixup 如果您使用magit则第4、5和6步是单个操作:提交,即时Fixup

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值