如何在分支之间插入 git 分支(并可能重命名)而不影响其他用户?

发布于 2025-01-14 04:16:33 字数 2108 浏览 2 评论 0原文

我有一个与其他用户共享的存储库,所以我希望有一个解决方案可以最大限度地减少其他人必须做的事情,如果有一种方法可以让他们直接进行更改,我会喜欢的。

这是我当前的 git 分支:

A--B---------F (master)
    \       /
     C--D--E (develop)

理想目标

A (master)
 \
  B---------F (stable)
   \       /
    C--D--E (develop)

但是如果这太难实现,特别是不会对已经拥有克隆的其他人进行复杂的更改(因为重命名),那么我不介意它看起来像这样或类似的:

A--B-------------F (master)
    \           /
     B'--------F' (stable)
      \       /
       C--D--E (develop)

简而言之:理想情况下,我很乐意创建一个 master空,等待来自的发布拉取请求stable,并将old master 重命名为stable master 应该是 master 的父级。

或者,如果重命名会使克隆​​存储库的其他人的事情变得复杂:我希望当前 masterdevelop 保持不变,但是我希望它们之间有一个名为 stable 的新分支,以便将来稳定的 develop 提交合并到 stable ,并可发布 stable< /code> 提交合并到大师

我猜想替代方案最终可能看起来更像这样:

A--B---------F-------------M (master)
   |         |\           /
   |         | `---I-----L (stable)
    \       /     /     /
     C--D--E--G--H--J--K (develop)

其中 G、H、J、K 是新的开发提交,I 和 L 是来自稳定 H 和 K 的合并提交,M 是可释放的合并提交我认为我可以通过将 master 分支为 stable 轻松完成,然后确保我从 develop 合并到 <代码>稳定,并且未来,从稳定master。或者说git有分支之间的父子关系的概念吗?

预先感谢您提供任何解决方案!

编辑:根据torek给出的答案,我们可以

  1. 签出 develop ,它不会改变
  2. create stable from master
  3. create main< /code> 来自提交 A 处的 master

它看起来像这样:

    ,---------------------M (main)
   /                     /
  /         ,-----I-----L (stable)
 /         /     /     /
A---------F     /     / (deprecated master)
 \       /     /     /
  B--C--D--G--H--J--K (develop)

执行以下操作后:

git checkout develop
git branch stable master
git branch main <first commit hash>

I have a repo that I share with other users, so I'd love a solution that minimizes what others have to do, if there's a way they can just pull the changes, I'd love that.

Here's my current git branching:

A--B---------F (master)
    \       /
     C--D--E (develop)

Ideal goal:

A (master)
 \
  B---------F (stable)
   \       /
    C--D--E (develop)

But if that's too hard to achieve, specially without incurring complicated changes for everyone else who already has a clone (because of renaming), then I wouldn't it mind it looking like this or similar:

A--B-------------F (master)
    \           /
     B'--------F' (stable)
      \       /
       C--D--E (develop)

In short: Ideally I'd love to create a new master that is empty, waiting for a release pull request from stable, and rename the old master to stable. The new master should be the parent of the old master.

Alternatively, if renaming complicates things for other people who have the repo cloned: I'd like the current master and develop to remain unchanged, but I want a new branch called stable between them so that stable develop commits get merged to stable in the future, and releasable stable commits are merged to master.

I guess there's a possibility that the alternative might end up looking more like this instead:

A--B---------F-------------M (master)
   |         |\           /
   |         | `---I-----L (stable)
    \       /     /     /
     C--D--E--G--H--J--K (develop)

Where G,H,J,K are new develop commits, I and L are merge commits from the stable H and K, and M is a releasable merge commit from L. This I assume I can easily do by branching off of master as stable, then making sure I'm merging from develop to stable, and stable to master, in the future. Or does git have a concept of parent-child relationship between branches?

Thank you in advance for any solutions!

EDIT: based on the answer given by torek, we could

  1. checkout develop which won't change
  2. create stable from master
  3. create main from master at commit A

And it would look like this:

    ,---------------------M (main)
   /                     /
  /         ,-----I-----L (stable)
 /         /     /     /
A---------F     /     / (deprecated master)
 \       /     /     /
  B--C--D--G--H--J--K (develop)

After doing the following:

git checkout develop
git branch stable master
git branch main <first commit hash>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧梦荧光笔 2025-01-21 04:16:33

Git 中的父/子关系仅与提交相关。在 Git 中,每个分支名称实际上只是该分支中最后一次提交的标签(可能是其他分支中的中间提交:K 就是这种情况)例如,上一个示例中的 L )。

分支名称​​可以任意移动,因此您可以在第一个示例中将masterF移回到A ,在创建指向提交 F 的新名称 stable 后:

git switch develop        # so that we're on one that doesn't move
git branch stable master
git branch -f master <hash-of-A>

这里棘手的部分是,拥有此存储库克隆的每个人都将拥有其克隆的 origin/master< /code> 指向提交的远程跟踪名称F 也是。这些克隆git fetch origin上更新自己的origin/master名称,以便它们指向A,但如果他们自己master名称指向现有提交F他们 Git软件将不会移动< em>他们的 master 分支名称只是因为origin/master 移动了,他们的 Git 软件将不愿意将 masterF“向后”移动他们的返回A,并且需要施加一些力。

如果您打算将 master 重命名为 main,现在是这样做的好时机:单独保留 master,创建新名称 main 指向现有提交 A,并告诉人们运行 git fetch。他们将获得一个指向 A 的新 origin/main。如果他们愿意的话,告诉他们以通常的方式创建自己的main——如果他们不使用它,他们就不需要它。告诉他们名称 master 现已死亡并将被删除,一旦他们根据需要对其他分支名称进行提交,他们应该删除自己的 master

请记住,每次提交都是 100% 只读,因此您无法将现有 F 更改为将 F' 作为父级。您始终可以进行提交,并且这些提交可以包含您喜欢的任何快照,以及您喜欢的任何父哈希 ID 列表(以便它们向后指向您所在点存在的任何提交)进行新的提交)。任何分支名称都可以指向任何提交,但是:

  • 每个克隆都有自己的分支名称;
  • Git 愿意将提交添加到分支(通过将名称“向前”滑动到新提交,只要在此过程中不会丢失旧提交,或者通过合并新提交)任何时候。它需要施加力量(如gitbranch-fgitreset)来“向后”移动分支名称(提交链接实际的方式,从子项向后移动到父母)。

因此,很容易获得此存储库的其他克隆来添加内容。这会自动发生:人们无论愿意与否都会获得新的提交。但让人们收回分支是很困难的:这需要每个人的手工工作。


关于您的编辑:

...它看起来像这样:

 ,---------------------M(主要)
   //
  / ,-----I-----L(稳定)
 ////
A---------F //(已弃用主控)
 \///
  B--C--D--G--H--J--K(展开)

一旦您进行了更多提交并进行了合并M,它最终会出现,是的。 (要从一开始就到达那里,您只需运行:

git branch main <hash-of-A>   # or git branch main master~2
git branch stable master

并在任何 GitHub 风格的服务器上,使用 Web 界面将“默认分支”设置为 main 现在,还可以选择删除master 完全设置默认分支,GitHub 将运行 git symbolic-ref HEAD refs/heads/main 或他们正在使用的任何软件中的等效项。)

The parent/child relationships in Git are tied solely to the commits. Each branch name, in Git, is really just a label for the last commit in that branch (which may be a middle commit in some other branch: that's the case with K and L in your last example, for instance).

Branch names can be moved arbitrarily, so you could move your master back from F to A in your first example, after creating new name stable pointing to commit F:

git switch develop        # so that we're on one that doesn't move
git branch stable master
git branch -f master <hash-of-A>

The tricky part here is that everyone who has a clone of this repository will have their clone's origin/master remote-tracking name pointing to commit F too. Those clones will update their own origin/master names on git fetch origin, so that they point to A, but if they have made their own master name pointing to existing commit F, their Git software will not move their master branch name just because origin/master moved—and their Git software will be reluctant to move their master "backwards", from F back to A, and will require some application of force.

Should you be inclined to rename master to main, this is a good time to do it: leave master alone, create new name main pointing to existing commit A, and tell people to run git fetch. They will get a new origin/main pointing to A. Tell them to create their own main in the usual way, if they wish—they don't need one if they're not using it. Tell them the name master is now dead and will be removed and they should remove their own master once they have their commits on some other branch name(s) as necessary.

Remember that every commit is 100% read-only, so you can't change the existing F to have F' as a parent. You can always make new commits, and those can contain whatever snapshot you like, and whatever list of parent hash IDs you like (so that they point backwards to any commit(s) that exist at the point you make the new commit). Any branch name can point to any commit, but:

  • each clone has its own branch names;
  • Git is willing to add commits to a branch (by sliding the name "forwards" to new commits, as long as it doesn't lose old ones in the process, or by merging in new commits) at any time. It requires applying force (as in git branch -f or git reset) to move a branch name "backwards" (the way the commit linkages actually go, from children backwards to parents).

So it's really easy to get other clones of this repository to add on stuff. That happens automatically: people get the new commits whether they want to or not. But it is hard to get people to retract branches: that takes manual work by each person.


Regarding your edit:

... And it would look like this:

    ,---------------------M (main)
   /                     /
  /         ,-----I-----L (stable)
 /         /     /     /
A---------F     /     / (deprecated master)
 \       /     /     /
  B--C--D--G--H--J--K (develop)

It would eventually, once you've made more commits and made the merge M, yes. (To get there from what you start with, you'd just run:

git branch main <hash-of-A>   # or git branch main master~2
git branch stable master

and on any GitHub-style servers, use the web interface to set up the "default branch" as main now, optionally also deleting master entirely. To set the default branch, GitHub will run git symbolic-ref HEAD refs/heads/main, or whatever is equivalent in whatever software they're using.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文