git 在推送之前将多个提交合并为一个
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5721566/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Combining Multiple Commits Into One Prior To Push
提问by Todd Hopkinson
This question pertains not only to how to accomplish this task, but to whether doing so is good or bad practice with Git.
这个问题不仅与如何完成这项任务有关,而且与使用 Git 这样做是好还是坏的做法有关。
Consider that locally I do most work on the master branch, but I have created a topical branch I will call "topical_xFeature". In the process of working on "topical_xFeature" and switching back and forth to do other work on the master branch, it turns out that I have made more than one commit on the "topical_xFeature" branch, but between each commit, I have done no push.
考虑到本地我在 master 分支上完成大部分工作,但我创建了一个主题分支,我将称之为“topical_xFeature”。在处理“topical_xFeature”和在master分支上来回切换做其他工作的过程中,结果我在“topical_xFeature”分支上做了不止一次commit,但是在每次commit之间,我都没有做推。
First, would you consider this bad practice? Would it not be wiser to stick with one commit per branch per push? In what cases would it be good to have multiple commits on a branch before a push is made?
首先,你会认为这种不好的做法吗?每次推送坚持每个分支提交一次不是更明智吗?在什么情况下,在推送之前在一个分支上进行多次提交会更好?
Second, how shall I best accomplish bringing the multiple commits on the topical_xFeature branch into the master branch for a push? Is it a nuisance to not worry about it and just do the push where multiple commits get pushed, or is it less annoying to somehow merge the commits into one and then push? Again, how to do this?
其次,我应该如何最好地将 topical_xFeature 分支上的多个提交带入主分支以进行推送?不担心它并且只是在推送多个提交的地方进行推送是否令人讨厌,或者以某种方式将提交合并为一个然后推送是否不那么烦人?再次,如何做到这一点?
回答by Brian Campbell
For your first question, no, there's nothing wrong with pushing multiple commits at once. Many times, you may want to break your work down into a few small, logical commits, but only push them up once you feel like the whole series is ready. Or you might be making several commits locally while disconnected, and you push them all once you're connected again. There's no reason to limit yourself to one commit per push.
对于您的第一个问题,不,一次推送多个提交并没有错。很多时候,你可能想把你的工作分解成几个小的、合乎逻辑的提交,但只有当你觉得整个系列都准备好了时才把它们推上去。或者您可能在断开连接时在本地进行多次提交,并在再次连接后将它们全部推送。没有理由将自己限制为每次推送一次。
I generally find that it's a good idea to keep each commit a single, logical, coherent change, that includes everything it needs to work (so, it does not leave your code in a broken state). If you have a two commits, but they would cause the code to be broken if you only applied the first one, it might be a good idea to squash the second commit into the first. But if you have two commits where each one makes a reasonable change, pushing them as separate commits is fine.
我通常发现让每个提交保持单一的、合乎逻辑的、连贯的更改是一个好主意,其中包括它需要工作的所有内容(因此,它不会使您的代码处于损坏状态)。如果您有两个提交,但如果您只应用第一个提交,它们会导致代码被破坏,那么将第二个提交压缩到第一个提交可能是个好主意。但是如果你有两个提交,每个提交都进行了合理的更改,那么将它们作为单独的提交推送就可以了。
If you do want to squash several commits together, you can use git rebase -i
. If you're on branch topical_xFeature
, you would run git rebase -i master
. This will open an editor window, with a bunch of commits listed prefixed by pick
. You can change all but the first to squash
, which will tell Git to keep all of those changes, but squash them into the first commit. After you've done that, check out master
and merge in your feature branch:
如果您确实想将多个提交压缩在一起,则可以使用git rebase -i
. 如果你在 branch topical_xFeature
,你会运行git rebase -i master
. 这将打开一个编辑器窗口,其中列出了一堆以pick
. 您可以将除第一个之外的所有更改为squash
,这将告诉 Git 保留所有这些更改,但将它们压缩到第一个提交中。完成后,检查master
并合并到您的功能分支:
git checkout topical_xFeature
git rebase -i master
git checkout master
git merge topical_xFeature
Alternatively, if you just want to squash everything in topical_xFeature
into master
, you could just do the following:
或者,如果您只想将所有内容压缩topical_xFeature
到 中master
,您可以执行以下操作:
git checkout master
git merge --squash topical_xFeature
git commit
Which one you choose is up to you. Generally, I wouldn't worry about having multiple smaller commits, but sometimes you don't want to bother with extra minor commits, so you just squash them into one.
你选择哪一个取决于你。一般来说,我不会担心有多个较小的提交,但有时你不想打扰额外的小提交,所以你只需将它们压缩成一个。
回答by Kondal Kolipaka
This is the way I generally follow to combine multiple Commits into a single commit before I push the code.
这是我在推送代码之前通常遵循的将多个提交合并为一个提交的方式。
To achieve this, I suggest you use 'squash' concept provided by GIT.
为此,我建议您使用GIT 提供的“壁球”概念。
Follow the below steps.
请按照以下步骤操作。
1) git rebase -i master(instead of masteryou can also use a specific commit)
1) git rebase -i master(你也可以使用特定的提交来代替master)
open the rebase interactive editor, where it will show all your commits. Basically where you need to identify the commits which you want to merge into a single commit.
打开 rebase 交互式编辑器,它将显示您的所有提交。基本上,您需要确定要合并到单个提交中的提交。
Imagine these are your commits and shown something like this in the editor.
想象一下,这些是您的提交,并在编辑器中显示了类似的内容。
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
It's important to note that these commits are listed in the opposite order than you normally see them using the log command. Means, the older commit will be shown first.
请务必注意,这些提交的列出顺序与您通常使用 log 命令看到的顺序相反。意味着,较旧的提交将首先显示。
2) Change 'pick' to 'squash'for last committed changes. something like shown below. Doing that so, your last 2 commits will be merged with the first one.
2)将上次提交的更改的“pick”更改为“squash”。如下所示。这样做,您的最后 2 个提交将与第一个合并。
pick f7f3f6d changed my name a bit
squash 310154e updated README formatting and added blame
squash a5f4a0d added cat-file
You can also use short form if you have lot of commits to combine:
如果您有很多提交要合并,您也可以使用简短格式:
p f7f3f6d changed my name a bit
s 310154e updated README formatting and added blame
s a5f4a0d added cat-file
for editing use 'i', it will enable the editor for insertion. Keep in mind top most(oldest) commit cannot be squashed as there is no previous commit to combine with. So it has to be picked or 'p'. Use 'Esc' to exit insert mode.
编辑使用'i',它将启用编辑器进行插入。请记住,最高(最旧)提交不能被压缩,因为没有先前的提交可以结合。所以它必须被选择或'p'。使用“Esc”退出插入模式。
3) Now, save the editorwith the following command. :wq
3) 现在,使用以下命令保存编辑器。 :wq
When you save that, you have a single commit that introduces the changes of all three previous commits.
当你保存它时,你有一个提交,它引入了所有三个先前提交的更改。
Hope this will help you.
希望这会帮助你。
回答by VonC
First: nothing tells you to only have one commit per branch per push: a push is a publication mechanism allowing you to publish a local history (i.e. a collection of commits) on a remote repo.
首先:没有什么会告诉您每次推送每个分支只有一个提交:推送是一种发布机制,允许您在远程存储库上发布本地历史记录(即提交的集合)。
Second: a git merge --no-ff topical_xFeature
would record on master as a single commit your topic work, before pushing master
.
(That way, you keep topical_xFeature
around for further evolutions, that you can record on master
as a single new commit on the next merge --no-ff.
If getting rid of topical_xFeature
is the goal, then git merge --squash
is the right option, as detailed in Brian Campbell's answer.)
第二:git merge --no-ff topical_xFeature
在推送之前,将在 master 上记录为单个提交您的主题工作master
。
(这样,您可以继续topical_xFeature
进行进一步的演变,您可以master
在下一次合并时将其记录为单个新提交 --no-ff。
如果摆脱topical_xFeature
是目标,那么这git merge --squash
是正确的选择,如Brian Campbell 所述的答案。)
回答by shiva kumar
Switch to the master branch and make sure you are up to date.
切换到 master 分支并确保您是最新的。
git checkout master
git fetch
this may be necessary (depending on your git config) to receive updates on origin/master
git fetch
这可能是必要的(取决于您的 git 配置)以接收有关 origin/master 的更新
git pull
Merge the feature branch into the master branch.
将功能分支合并到主分支。
git merge feature_branch
Reset the master branch to origin's state.
将 master 分支重置为 origin 的状态。
git reset origin/master
Git now considers all changes as unstaged changes. We can add these changes as one commit. Adding . will also add untracked files.
Git 现在将所有更改视为未暂存的更改。我们可以将这些更改添加为一次提交。添加 . 还将添加未跟踪的文件。
git add --all
git commit
Ref: https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit
参考:https: //makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit
回答by Eddy Ekofo
First choose which commit you want everything to come after.
git reflog 5976f2b HEAD@{0}: commit: Fix conflicts 80e85a1 HEAD@{1}: commit: Add feature b860ddb HEAD@{2}: commit: Add something
Reset to your selected head (I have chosen
HEAD@{2}
)git reset b860ddb --soft
git status
(just to be sure)Add your new commit
git commit -m "Add new commit"
首先选择你想要的所有提交。
git reflog 5976f2b HEAD@{0}: commit: Fix conflicts 80e85a1 HEAD@{1}: commit: Add feature b860ddb HEAD@{2}: commit: Add something
重置为您选择的头部(我已选择
HEAD@{2}
)git reset b860ddb --soft
git status
(只是要确定)添加您的新提交
git commit -m "Add new commit"
Note: HEAD@{0}
& HEAD@{1}
Are now merged into 1 commit, this can be done for multiple commits also.
注意:HEAD@{0}
&HEAD@{1}
现在合并为 1 个提交,这也可以用于多个提交。
git reflog
again should display:
git reflog
再次应显示:
git reflog
5976f2b HEAD@{0}: commit: Add new commit
b860ddb HEAD@{1}: commit: Add something
回答by liwugang
A Tool To Automate Multiple Commits Into One
一种将多个提交自动化为一个的工具
as Kondal Kolipaka says. Using "git rebase -i"
正如孔达尔·科利帕卡所说。使用“git rebase -i”
The logic of "git rebase"
“git rebase”的逻辑
When using "git rebase -i", git generates the git-rebase-todo file in the current .git/rebase-merge directory, and then invokes the git editor to let users edit the git-rebase-todo file for processing. So the tool needs to meet:
使用“git rebase -i”时,git会在当前的.git/rebase-merge目录下生成git-rebase-todo文件,然后调用git编辑器让用户编辑git-rebase-todo文件进行处理。所以该工具需要满足:
- Modify the git editor to the tool which we provided;
- The tool processes the git-rebase-todo file.
- 将git编辑器修改为我们提供的工具;
- 该工具处理 git-rebase-todo 文件。
Modify the default git editor
修改默认的git编辑器
git config core.editor #show current default git editor
git config --local --replace-all core.editor NEW_EDITOR # set the local branch using NEW_EDITOR as git editor
So, the tool need change the git editor and process the git-rebase-todo file. The tool using python below:
因此,该工具需要更改 git 编辑器并处理 git-rebase-todo 文件。下面使用python的工具:
#!/usr/bin/env python3
#encoding: UTF-8
import os
import sys
def change_editor(current_file):
os.system("git config --local --replace-all core.editor " + current_file) # Set current_file as git editor
os.system("git rebase -i") # execute the "git rebase -i" and will invoke the python file later with git-rebase-todo file as argument
os.system("git config --local --replace-all core.editor vim") # after work reset the git editor to default
def rebase_commits(todo_file):
with open(todo_file, "r+") as f:
contents = f.read() # read git-rebase-todo's content
contents = contents.split("\n")
first_commit = True
f.truncate()
f.seek(0)
for content in contents:
if content.startswith("pick"):
if first_commit:
first_commit = False
else:
content = content.replace("pick", "squash") # replace the pick to squash except for the first pick
f.write(content + "\n")
def main(args):
if len(args) == 2:
rebase_commits(args[1]) # process the git-rebase-todo
else:
change_editor(os.path.abspath(args[0])) # set git editor
if __name__ == "__main__":
main(sys.argv)
Ref: https://liwugang.github.io/2019/12/30/git_commits_en.html
参考:https: //liwugang.github.io/2019/12/30/git_commits_en.html