有没有办法为Git中的每个远程或分支设置不同的作者?
我脑海中唯一想到的就是使用Git钩子(post-checkout / post-commit)编写脚本,它会检查当前分支并更改作者,但它只适用于分支,而不是远程和不# 39;看起来很优雅。还有其他解决方案吗?
更新
我感谢你的回答,但为什么你们需要知道我这样做的原因? :)无论如何,让我为你澄清一下:
我有2个遥控器的本地回购:remoteA
和remoteB
。另外,我有2个分支:branchA
和branchB
。每个遥控器都设置为分别跟踪这些分支:
git remote add -t branchA remoteA [remoteA-URL]
git remote add -t branchB remoteB [remoteB-URL]
有2个团队对此存储库进行了更改: TeamA 和 TeamB 。我通常会将提交从remoteB/branchB
提取到branchB
,挑选或压缩,并将一些提交合并到branchA
并推送到remoteA/branchA
。有时我也会将remoteA/branchA
的提交合并到branchB
。现在,问题是 - 我需要在不同的用户名/电子邮件下推送到每个远程的提交。 usernameA
为remoteA
,远程usernameB
为remoteB
。目前,我rebase
编辑提交cherry-pick && merge
之后只是commit --amend --author
,但我想以某种方式自动执行此操作。我知道我可以创建2个本地存储库并为每个设置不同的配置,包括作者姓名首字母和本地存储库之间的推/拉。但我想把它放在一个当地的回购中。
你还需要知道 - 为什么我需要这些?好吧,出于个人原因。
在提问后,我发现有pre-push
个问题,这有助于自动commit --amend --author
,但这只是想到了,我还没有在实践中尝试过。当我这样做时,我会在这里添加结果和/或代码。
答案 0 :(得分:2)
编辑:问题已更新,我的原始答案仅针对其他问题。
显然有:
(目前尚不清楚两个不同的团队是否会推送到两个不同的遥控器,尽管这样做有意义。)
在这种情况下,两个分支实际上是完全不同的发展方式。如果你跨过它们(通过合并),你可以选择其他分支的历史记录,包括提交作者。没有办法解决这个问题。如果您确实在两个方向上合并,那么最终您的两个ID将显示在"其他"分支。
你需要理解的是,每个提交通过其父提交ID记录(间接地,但不可磨灭地)在它之前的开发的整个历史。
commit-ID是一个字符串(SHA-1,在badc0ffee
输出中看起来像git log
等)。存储库中的每个提交都只有一个唯一的ID。提交ID 是提交的内容的加密校验和:作者,电子邮件,日期,父提交ID列表,文本消息和源树ID。如果您要更改任何,则必须进行新的提交 - 包含更改的副本 - 您将获得一个新的不同的 ID。
因为每个提交都存储其父提交ID,所以您可以从任何给定提交开始并查找其所有父提交。使用这些提交,您可能会找到他们的父母,等等。这就是了解谁做了什么以及何时做的历史:每个提交都有作者(和提交者),日期,消息和附加的源树。
我们可以绘制这些提交的图表。让我们使用branchA
和branchB
执行此操作,并假设它们非常简单且线性开头:
A1 - A2 - A3 <-- branchA
B1 - B2 - B3 <-- branchB
每个ID(A1
到A3
和B1
到B3
)代表一些长SHA-1;我们并不真正关心价值观,而且它们太大而无法理解,所以让我们假设我们有两位数的SHA-1。
现在让我们假设您决定以A <A@A>
上的用户branchA
进行提交。
A1 - A2 - A3 - A4 <-- branchA
B1 - B2 - B3 <-- branchB
您的新提交A4
记录其父ID A3
及其作者A <A@A>
。这永远不会改变:它是身份A4
的一部分。如果您尝试更改它,您将获得一个新的,不同的SHA-1。
现在,让我们将A4
中所做的更改复制到branchB
,但使用您的其他名称B <B@B>
和父B3
。这或多或少是git cherry-pick
修改作者的效果,或git cherry-pick -n
后跟单独的git commit
作为用户-B的效果。你会得到一个新的,不同的提交ID,我只假设它是B4
:
A1 - A2 - A3 - A4 <-- branchA
B1 - B2 - B3 - B4 <-- branchB
现在假设您稍后决定合并(真正的合并,而不是压缩合并,实际上并不是合并 1 )。合并提交只是记录两个或多个父提交ID的提交。我们假设这个合并继续branchA
并合并branchB
,从那时起又开发了更多:
A1 - A2 - A3 - A4 - A5 - M <-- branchA
/
B1 - B2 - B3 - B4 - B5 <-- branchB
分支标签branchB
指向您的提交B5
,但B5
指向您的B4
(写为用户B <B@B>
)。分支标签branchA
现在指向合并提交M
,它指向两个父项:A5
和B5
。关注B5
返回B4
,A5
返回A4
,任何有权提交M
的人 - 一旦推送他们就会拥有branchA
到remoteA
- 将能够看到用户B <B@B>
几乎同时与用户A <A@A>
做同样的事情。此外,如果在B1
之前提交B5
到remoteA
之前不存在,则推送M
将导致它们存在,因为添加新提交(无论是push
}或fetch
)带来了它的所有历史。提交M
的历史记录需要B5
,这需要B4
,依此类推。
如果您在某个时候将branchA
的提交合并到branchB
的历史记录中,您还会带来该分支的所有历史记录。
如果您从未合并分支机构,则可以将其历史记录分开,但是您自己更难以将更改结合在一起。
1 使用git merge --squash
时,git像往常一样通过正常的合并机制来构建工作树,但它不会记录要合并的提交,也不会记录自己做一个新的提交。当您自己提交结果时,它只是一个常规(非合并,单父)提交。所以它实际上不是合并:它不会被记录在提交图中,并且git无法利用记录的信息来使未来的合并更容易。
[原帖在下面]
好的,我从评论中看到,我将在这里解释的目标是使用一个作者/电子邮件对进行一次提交,但是当他们被推送时,将这些提交复制到新的(不同)提交相同的树,但不同的作者/电子邮件对。
然后提交作者/电子邮件A <A@A>
然后推送到remoteA
,并且(相同)提交,但作者/电子邮件B <B@B>
被推送到remoteB
请注意,remoteA
和remoteB
不会共享提交,并且可能会失去同步(例如,当你去推送时,一个人失败了)并且它不容易拥有两个遥控器互相交谈以重新同步。 (这并非不可能;他们只需要做同样的过滤,你就是在这里做的。)
[如果这不是实际目标(例如,如果您只需要以remoteB
身份向另一个用户进行身份验证,但可以推送包含A <A@A>
作为其作者字符串的提交),那么其余部分这个答案毫无意义。]
总的来说,我不认为这是一个非常好的计划,但可以做到。这是大纲,有两种不同的方法有各种缺陷:
在提交时生成提交副本(例如,使用提交后挂钩)。这假定您只提交一次,而不必修改或改变。</ p>
在发布时制作提交副本,例如,在git push
之前(编写一个审核提交的脚本,根据需要复制它们,然后执行两次推送)。这可能是一种优越的方法,尽管它会使推动速度变慢。特别是它允许您替换从未向上游发送的提交:您仍然可以使用git commit --amend
和git rebase
。
在这两种情况下,如果一个或两个遥控器都有push
之前必须包含的新提交,则可能会遇到问题。例如,假设remoteA
(将获取由A <A@A>
编写的三个新提交)现在全部同步并且您推送三个提交。他们安全抵达,一切都很好。但是现在您列出的B <B@B>
所写的副本将被推送到remoteB
;但事实证明remoteB
已经自己获得了一些新的提交,并且副本本身需要重新定位。而且,你可能会消灭他们的&#34;变化(无论他们&#34;他们&#34;是否发生了remoteB
的变化。这个将与我在下面描述的树重置方法一起发生。
无论如何,要制作一份提交副本,这是一种欺骗方式。首先假设您有一个名为devel-for-A
的分支,您可以在其中将作者设置为A
并将电子邮件设置为A@A
进行提交;并且你有一个并行分支devel-for-B
,你可以在其中复制这些提交但是与另一个作者和电子邮件一起复制。
$ git checkout devel-for-A
... hack away ...
$ git commit -m 'new stuff'
现在将这些复制到devel-for-B
,我们只需在提交期间替换正确的HEAD
,然后将其交换回来:
$ git symbolic-ref HEAD refs/heads/devel-for-B
$ git commit -C devel-for-A --reset-author --author='B <B@B>'
$ git symbolic-ref HEAD refs/heads/devel-for-A
请注意,您可以使用-C
复制上一次提交中的邮件,但您还必须使用--reset-author
。在这里,我使用了devel-for-A
命名提交的事实。如果您在推送之前稍后进行复制,则不会出现这种情况。在这种情况下,简单(但不是非常有效)的方法是使用git rm -r .; git checkout $rev -- .
将树从另一个分支导入到当前分支(因此您可以使用devel-for-B
然后导入提交来自devel-for-A
)。见下几段。
如果您在推送之前复制提交,则需要使用git rev-list
生成要复制的ID(这是$rev
,但您需要使用一些shell脚本代码它)。要知道要复制哪些提交,您可能需要添加额外的引用以跟踪推送到remoteB
的上一个成功ID(假设您正在从devel-for-A
分支复制到devel-for-B
{1}}分支)。 (我没有仔细考虑过这一点的所有细节。远程分支标签会自动更新,因此您可以知道哪些提交可以通过,但您可能不知道它们映射到哪个原始A
- 分支提交。)
如果您正在集中复制提交,那么使用git checkout
执行此操作是过度的:您可以将提交读入索引。基本上,您需要执行filter-branch
所做的事情(因此请查看该脚本),但不是在之后重写现有的分支标签(devel-for-A
),而是(重新)编写devel-for-B
标签。
答案 1 :(得分:0)
对不起,这个想法没有意义。
作者是提交的一部分。提交可能是多个分支的一部分。在这种情况下你想要哪位作者?
此外,远程仅在推送时相关,但您需要在提交时设置作者,这在您决定将该提交推送到任何远程之前很久。无法告知提交时间您希望稍后推送该提交的远程数据。
也许你应该解释为什么你在考虑这个想法。似乎有一个不同的问题是核心问题。