在 git 中进行“临时”提交的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3953497/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 09:17:55  来源:igfitidea点击:

What's the best way to have a "temporary" commit in git?

gittemporary

提问by Rwky

Say I have a project with two branches master and dev. I have a bunch of commits on dev for a special event which once tested are merged into master. Then after the event is over I want to remove the event specific code. However a git reset won't do since other commits have been made since the event code was added.

假设我有一个有两个分支 master 和 dev 的项目。我有一堆关于 dev 的提交,用于一个特殊事件,一旦测试就合并到 master 中。然后在事件结束后我想删除事件特定的代码。但是 git reset 不会执行,因为自添加事件代码以来已经进行了其他提交。

Currently I use git checkout to checkout the files from before the event was merged in and then use git diff to re-add in the changes that have been made since the event was committed. This seems like a very messy method to me.

目前,我使用 git checkout 来检出事件合并之前的文件,然后使用 git diff 重新添加自事件提交以来所做的更改。这对我来说似乎是一种非常混乱的方法。

Does anyone have a better solution for having temporary code in a project?

有没有人有更好的解决方案来在项目中使用临时代码?

Edit: To be clear the changes need to be committed, pushed, uncommitted, pushed.

编辑:要明确更改需要提交、推送、未提交、推送。

采纳答案by rfunduk

Take master and create a branch: git checkout -b special-event, make/apply your changes. Once the event is over, simply switch back to master and abandon/delete the branch.

获取 master 并创建一个分支:git checkout -b special-event,进行/应用您的更改。一旦事件结束,只需切换回 master 并放弃/删除分支。

In order to continue making changes, make them on master and merge them into the special branch as you go. git checkout master... make changes ... git checkout special-event; git merge master.

为了继续进行更改,请在 master 上进行更改,并随时将它们合并到特殊分支中。git checkout master...让变化...... git checkout special-event; git merge master

Alternatively, make all your special-event related changes in one commit, then use git revertwhen you want to roll them out and specify just that commit.

或者,在一次提交中进行所有与特殊事件相关的更改,然后git revert在您想要推出它们并仅指定该提交时使用。

回答by user1654465

"Temporary code"? In git we use branches for that. Commits are very lightweight in git, and branches, being just names (or references) for commits with a tiny bit of logic attached, are super lightweight compared to other systems.

“临时密码”?在 git 中,我们为此使用分支。提交在 git 中是非常轻量级的,而分支只是带有一点逻辑的提交的名称(或引用),与其他系统相比是超轻量级的。

The tiny bit of logic is just that the reference is automatically updated to the last commit. That's pretty much all of what a branch is. That means creating and destroying branches in git is fast, simple and even safe, since nothing is really created or deleted. After a delete you can still reference to the branch head by commit-id (yes, it's still there until it's garbage-collected and even that happens only if there's no other reference to it).

一点点逻辑就是引用会自动更新到最后一次提交。这几乎就是分支的全部内容。这意味着在 git 中创建和销毁分支是快速、简单甚至安全的,因为没有真正创建或删除任何内容。删除后,您仍然可以通过 commit-id 引用分支头(是的,它仍然存在,直到它被垃圾收集为止,即使只有在没有其他引用时才会发生这种情况)。

Almost every command in git takes references to a commit as parameters. That's true for git merge as well. You're not merging branches, you're merging commits. Yes, you type 'git merge ', but again, a branch is just a name for a commit. Nothing more than that. And since all you need is grouping the commits for the event together, just give them a name.

git 中几乎每个命令都将提交的引用作为参数。对于 git merge 也是如此。您不是在合并分支,而是在合并提交。是的,您输入 'git merge ',但同样,分支只是提交的名称。仅此而已。由于您需要的只是将事件的提交分组在一起,只需给它们一个名称即可。

So the right thing to do is to create a branch for the event. Or possibly, two: 'event-master' and 'event-dev'. Now, you develop code for the event in 'event-dev'. Should you bump into a bug that needs to be fixed in the main code, stash and switch to your normal 'dev' branch, code the fix in and commit. Switch back to 'event-dev', merge from 'dev', and pop the stash. Go on developing, once done, commit and test. If it's ok, merge 'event-dev' into 'event-master'. This would contain also the fix. Note that the fix is not in 'master' yet.

所以正确的做法是为事件创建一个分支。或者可能是两个:'event-master' 和 'event-dev'。现在,您在“event-dev”中为事件开发代码。如果您遇到需要在主代码中修复的错误,请隐藏并切换到正常的“开发”分支,编写修复代码并提交。切换回 'event-dev',从 'dev' 合并,然后弹出 stash。继续开发,一旦完成,提交和测试。如果没问题,将“event-dev”合并到“event-master”中。这也将包含修复。请注意,该修复程序尚未在“master”中。

If you need the fix merged into 'master', you just do it the usual way, as the fix is in 'dev'.

如果您需要将修复程序合并到“master”中,您只需按照通常的方式进行,因为修复程序位于“dev”中。

Basicly in this setup you can:

基本上在此设置中,您可以:

  • develop the main code as usual: you commit to 'dev', test, and merge into 'master';

  • develop the event specific code in a similar manner: you commit to 'event-dev', test, and merge into 'event-master'; it's just the same workflow;

  • intermix the two workflows; commit and switch branch, or use git stash;

  • merge branches (almost) freely; you can merge 'master' into 'event-dev', if master is somehow updated and you need the changes for the event; you can merge 'dev' into 'event-dev', if you desperately need the changes for the event and can't wait for the usual testing cycle that pushes them into 'master'. git would do this as far as the merges are clean, that is unless you changed the same piece of code in two different ways in the two -dev branches (this of course is a special case that needs to be handled);

  • 像往常一样开发主要代码:你提交'dev',测试并合并到'master';

  • 以类似的方式开发特定于事件的代码:您提交“event-dev”,测试并合并到“event-master”中;这只是相同的工作流程;

  • 混合两个工作流程;提交和切换分支,或使用 git stash;

  • 合并分支(几乎)自由;您可以将 'master' 合并到 'event-dev',如果 master 以某种方式更新并且您需要对事件进行更改;您可以将“dev”合并到“event-dev”中,如果您迫切需要事件的更改并且不能等待通常的测试周期将它们推入“master”。只要合并是干净的,git 就会这样做,除非您在两个 -dev 分支中以两种不同的方式更改了同一段代码(这当然是需要处理的特殊情况);

If you need extra flexibility, create more branches. For super flexibility, you can cherry-pick individual commits into a branch, but in general I advise against that (do it only if you really know what you're doing).

如果您需要额外的灵活性,请创建更多分支。为了获得超强的灵活性,您可以将单个提交挑选到一个分支中,但总的来说,我建议不要这样做(只有在您真正知道自己在做什么的情况下才这样做)。

Finally, I should point out that this workflow is so natural in git. Actually, developing in 'dev' and pulling changes in 'master' is not even the best generally speaking. It's customary to create a dev branch for each feature or module you're developing, and merge those branches in 'dev'.

最后,我应该指出这个工作流程在 git 中是如此自然。实际上,在'dev'中开发并在'master'中拉动变化一般来说甚至不是最好的。通常为您正在开发的每个功能或模块创建一个 dev 分支,并将这些分支合并到“dev”中。

I think the right mindset when using git is: "what do I feel like to code today? feature X. Good, let's create branch 'feature-x' and start hacking.". That event of yours is no different.

我认为使用 git 时正确的心态是:“我今天编码的感觉是什么?功能 X。好的,让我们创建分支 'feature-x' 并开始黑客攻击。”。你的那个事件也不例外。

Now, I know that what I'm telling you is how you should have done things from the start, and that doesn't help much right now. You need to fix your tree, since - so it seems - you have the changes for the event mixed with the normal changes into your 'dev' branch. So your problem is how to properly create 'event-dev' with only the changes for the event and remove them from 'dev' at the same time.

现在,我知道我要告诉你的是你从一开始就应该如何做事,现在这没有多大帮助。您需要修复您的树,因为 - 看起来 - 您将事件的更改与“开发”分支中的正常更改混合在一起。所以你的问题是如何正确地创建'event-dev',只包含事件的更改,并同时从'dev'中删除它们。

Time to rewrite history. How hard that will be, it depends on the nature of the changes. For example, if all changes belong to a single directory, things can be easier.

是时候改写历史了。这有多难,这取决于变化的性质。例如,如果所有更改都属于一个目录,则事情会更容易。

Here's what I would do (knowing no better):

这是我会做的(不知道更好):

  • examine the history with git log;

  • find the commit that's right before the first event specific change, take notice of its commit-id: this is the 'day-0' commit;

  • create a branch named 'newdev' pointing at that commit. Do this in a clean tree, that is commit before doing this: git checkout <commit-id> -b newdev;

  • create 'event-dev': git checkout -b event-dev;

  • you've got now two branches both pointing at the 'day-0' commit;

  • now look at the history again (git log dev), you need to follow it commit by commit;

  • I'm assuming that each commit following 'day-0' is either a commit that belongs to the main code, or one that belongs to the event only. What you have to do is to cherry-pick them in the right branch, 'newdev' if it's main code, 'event-dev' if it's event-code; do it one a time, in the right order (from 'day-0' to today);

  • if you're very lucky, no commit that ends up in 'newdev' depends on commits in 'event-dev' and viceversa; you're kinda done; you may want to rename (keep them around) the current master and dev to master-old and dev-old, then rename newdev to dev, create master from dev, event-master from event-dev, and you're set;

  • if you're a bit less lucky, at times you'll have to merge 'newdev' into 'event-dev', because some commits depends on changes made in the main code, which is fine, tho; if you're feeling daring here, it's time to read about git rebase; but rebase don't unless you have to;

  • or (worse) some commits in 'newdev' depend on changes in 'event-dev'... oops, that event-specific code turns out to be not so event-specific, if the main branch needs it. Some merging required;

  • or (bad) one commit contains both kind of changes: divide and conquer (you need to separate the changes and apply them to the right branch), that means you're splitting the commit in two;

  • or something else I can't imagine now since I don't have enough details about your tree.

  • 用 git log 查看历史记录;

  • 找到第一个事件特定更改之前的提交,注意其提交 ID:这是“第 0 天”提交;

  • 创建一个名为“newdev”的分支,指向该提交。在干净的树中执行此操作,即在执行此操作之前提交: git checkout <commit-id> -b newdev;

  • 创建“事件开发”:git checkout -b event-dev;

  • 你现在有两个分支都指向 'day-0' 提交;

  • 现在再次查看历史记录(git log dev),您需要按提交跟踪它;

  • 我假设“第 0 天”之后的每个提交要么是属于主代码的提交,要么是仅属于事件的提交。你需要做的是在正确的分支中挑选它们,'newdev' 如果是主代码,'event-dev' 如果是事件代码;按照正确的顺序(从“第 0 天”到今天)一次做一次;

  • 如果你很幸运,那么在 'newdev' 中的提交不会依赖于在 'event-dev' 中的提交,反之亦然;你已经完成了;您可能希望将当前的 master 和 dev 重命名(保留它们)为 master-old 和 dev-old,然后将 newdev 重命名为 dev,从 dev 创建 master,从 event-dev 创建 event-master,然后就设置好了;

  • 如果您不太幸运,有时您必须将“newdev”合并到“event-dev”中,因为某些提交取决于主代码中所做的更改,这很好,不过;如果你觉得这里很大胆,是时候阅读 git rebase 了;但除非你必须,否则不要变基;

  • 或者(更糟糕的是)'newdev' 中的某些提交取决于'event-dev' 中的更改...哎呀,如果主分支需要它,那么特定于事件的代码实际上并不是那么特定于事件的。需要一些合并;

  • 或者(坏)一个提交包含两种更改:分而治之(您需要将更改分开并将它们应用到正确的分支),这意味着您将提交分成两部分;

  • 或者其他我现在无法想象的东西,因为我没有足够的关于你的树的细节。

It could be a breeze or a nightmare. Inspect each commit beforehand (git show, you can look at it as a patch), decide what to do (eventually don't cherry-pick, just editing the files could be easier), if not sure - guess what - create a branch, work in there, see what happens, merge it if happy, drop it otherwise and try again.

这可能是微风或噩梦。事先检查每个提交(git show,您可以将其视为补丁),决定要做什么(最终不要随意挑选,只需编辑文件可能会更容易),如果不确定 - 猜猜看 - 创建一个分支,在那里工作,看看会发生什么,如果满意就合并它,否则放弃它,然后再试一次。

I haven't mentioned it so far, but of course you can make a copy of the whole tree, git files included, and work on the copy to be 100% safe.

到目前为止我还没有提到它,但是当然你可以制作整个树的副本,包括 git 文件,并在副本上工作以确保 100% 安全。

Doing it right from the start is rather easy. Fixing it now, well, good luck. :)

从一开始就做对是相当容易的。现在修复它,好吧,祝你好运。:)

回答by Dan Rosenstark

Roll up your commits following my not-patented method:

按照我的非专利方法汇总您的提交:

# work on a new branch
git checkout -b event-36
git commit -a -m "all broken dammit"
git commit -a -m "fixed that damn code"
git commit -a -m "almost ready, going to eat lunch"
git commit -a -m "It's done!"

# other people might be working on master in the meantime, so
git checkout master
git checkout -b erasemeImmediately
git merge event-36
git reset --soft master # THE KEY TO THE WHOLE THING: SOFT RESET!
git commit -a -m "Event 36, all code in one commit"

git checkout master
git merge erasemeImmediately

You can do this with reflog, but then you'll need a recent CS degree (i.e, it's hard to understand).

你可以用 来做到这一点reflog,但是你需要一个最近的 CS 学位(即,这很难理解)。

Now your commit is one single one. Now you can use revert or do cherry-pick your way to a branch without it.

现在你的提交是一个单一的。现在你可以使用 revert 或者在没有它的情况下选择你的方式到一个分支。

回答by dgnorton

git checkout -b event

git checkout -b event

...make specific event change...

...进行特定的事件更改...

git commit -am "specific event change"

git commit -am "specific event change"

...make another specific event change...

...进行另一个特定的事件更改...

git commit -am "another specific event change"

git commit -am "another specific event change"

At this point, the masterbranch is still intact and the event specific changes are on the eventbranch. If changes are made to the master branch that are also needed in the eventbranch, use rebase...

此时,分支仍然完好无损,事件特定的更改在事件分支上。如果对事件分支中也需要的主分支进行了更改,请使用rebase...

git rebase master

git rebase master

Another answer suggested merging masterinto eventbut rebaseis usually the better approach. A rebasepeels the commits made on the topic branch off, pulls the the updated masterforward and then reapplies the topic branch changes on top...as if the topic branch changes were made to the most recent version of master.

另一个答案建议将master合并到eventrebase通常是更好的方法。一个底垫换肤提交的话题岔开做,拉动更新的向前,然后重新应用在上面的特性分支的变化......仿佛话题分支变化到最新版本大师制作。

In your scenario, when the event is over, simply delete the eventbranch.

在您的场景中,当事件结束时,只需删除事件分支。

回答by cmcginty

git revert

git恢复

It will remove any commit, or range of commits that you need to undo. It is also safe to push to a public repo.

它将删除您需要撤消的任何提交或提交范围。推送到公共回购也是安全的。

回答by pragman

In my experience, some special events have a way of recurring. So an alternate solution to consider here is to create a configuration option to enable handling the special event, so that it can be turned on and off as and when needed.

根据我的经验,一些特殊事件有一种重复发生的方式。因此,这里要考虑的替代解决方案是创建一个配置选项来启用处理特殊事件,以便可以在需要时打开和关闭它。

回答by Splashdust

I beleive stashdoes what you want.

我相信stash可以满足您的需求。