每个远程或分支的作者

时间:2014-07-08 06:14:20

标签: git bash git-branch githooks

有没有办法为Git中的每个远程或分支设置不同的作者?

我脑海中唯一想到的就是使用Git钩子(post-checkout / post-commit)编写脚本,它会检查当前分支并更改作者,但它只适用于分支,而不是远程和不# 39;看起来很优雅。还有其他解决方案吗?

更新

我感谢你的回答,但为什么你们需要知道我这样做的原因? :)无论如何,让我为你澄清一下:

我有2个遥控器的本地回购:remoteAremoteB。另外,我有2个分支:branchAbranchB。每个遥控器都设置为分别跟踪这些分支:

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。现在,问题是 - 我需要在不同的用户名/电子邮件下推送到每个远程的提交usernameAremoteA,远程usernameBremoteB。目前,我rebase编辑提交cherry-pick && merge之后只是commit --amend --author,但我想以某种方式自动执行此操作。我知道我可以创建2个本地存储库并为每个设置不同的配置,包括作者姓名首字母和本地存储库之间的推/拉。但我想把它放在一个当地的回购中。

你还需要知道 - 为什么我需要这些?好吧,出于个人原因。

提问后,我发现有pre-push个问题,这有助于自动commit --amend --author,但这只是想到了,我还没有在实践中尝试过。当我这样做时,我会在这里添加结果和/或代码。

2 个答案:

答案 0 :(得分:2)

编辑:问题已更新,我的原始答案仅针对其他问题。

显然有:

  1. 两个不同的遥控器
  2. 两个不同的团队
  3. 处理两个不同的发展方向
  4. (目前尚不清楚两个不同的团队是否会推送到两个不同的遥控器,尽管这样做有意义。)

    在这种情况下,两个分支实际上是完全不同的发展方式。如果你跨过它们(通过合并),你可以选择其他分支的历史记录,包括提交作者。没有办法解决这个问题。如果您确实在两个方向上合并,那么最终您的两个ID将显示在"其他"分支。

    你需要理解的是,每个提交通过其父提交ID记录(间接地,但不可磨灭地)在它之前的开发的整个历史

    commit-ID是一个字符串(SHA-1,在badc0ffee输出中看起来像git log等)。存储库中的每个提交都只有一个唯一的ID。提交ID 提交的内容的加密校验和:作者,电子邮件,日期,父提交ID列表,文本消息和源树ID。如果您要更改任何,则必须进行新的提交 - 包含更改的副本 - 您将获得一个新的不同的 ID。

    因为每个提交都存储其父提交ID,所以您可以从任何给定提交开始并查找其所有父提交。使用这些提交,您可能会找到他们的父母,等等。这就是了解谁做了什么以及何时做的历史:每个提交都有作者(和提交者),日期,消息和附加的源树。

    我们可以绘制这些提交的图表。让我们使用branchAbranchB执行此操作,并假设它们非常简单且线性开头:

    A1 - A2 - A3   <-- branchA
    
    B1 - B2 - B3   <-- branchB
    

    每个ID(A1A3B1B3)代表一些长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,它指向两个父项:A5B5。关注B5返回B4A5返回A4,任何有权提交M的人 - 一旦推送他们就会拥有branchAremoteA - 将能够看到用户B <B@B>几乎同时与用户A <A@A>做同样的事情。此外,如果在B1之前提交B5remoteA之前不存在,则推送M将导致它们存在,因为添加新提交(无论是push }或fetch)带来了它的所有历史。提交M的历史记录需要B5,这需要B4,依此类推。

    如果您在某个时候将branchA的提交合并到branchB的历史记录中,您还会带来该分支的所有历史记录。

    如果您从未合并分支机构,则可以将其历史记录分开,但是您自己更难以将更改结合在一起。


    1 使用git merge --squash时,git像往常一样通过正常的合并机制来构建工作树,但它不会记录要合并的提交,也不会记录自己做一个新的提交。当您自己提交结果时,它只是一个常规(非合并,单父)提交。所以它实际上不是合并:它不会被记录在提交图中,并且git无法利用记录的信息来使未来的合并更容易。


    [原帖在下面]

    好的,我从评论中看到,我将在这里解释的目标是使用一个作者/电子邮件对进行一次提交,但是当他们被推送时,将这些提交复制到新的(不同)提交相同的树,但不同的作者/电子邮件对。

    然后提交作者/电子邮件A <A@A>然后推送到remoteA,并且(相同)提交,但作者/电子邮件B <B@B>被推送到remoteB

    请注意,remoteAremoteB不会共享提交,并且可能会失去同步(例如,当你去推送时,一个人失败了)并且它不容易拥有两个遥控器互相交谈以重新同步。 (这并非不可能;他们只需要做同样的过滤,你就是在这里做的。)

    [如果这不是实际目标(例如,如果您只需要以remoteB身份向另一个用户进行身份验证,但可以推送包含A <A@A>作为其作者字符串的提交),那么其余部分这个答案毫无意义。]

    总的来说,我不认为这是一个非常好的计划,但可以做到。这是大纲,有两种不同的方法有各种缺陷:

    1. 在提交时生成提交副本(例如,使用提交后挂钩)。这假定您只提交一次,而不必修改或改变。<​​/ p>

    2. 在发布时制作提交副本,例如,在git push之前(编写一个审核提交的脚本,根据需要复制它们,然后执行两次推送)。这可能是一种优越的方法,尽管它会使推动速度变慢。特别是它允许您替换从未向上游发送的提交:您仍然可以使用git commit --amendgit rebase

    3. 在这两种情况下,如果一个或两个遥控器都有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)

对不起,这个想法没有意义。

作者是提交的一部分。提交可能是多个分支的一部分。在这种情况下你想要哪位作者?

此外,远程仅在推送时相关,但您需要在提交时设置作者,这在您决定将该提交推送到任何远程之前很久。无法告知提交时间您希望稍后推送该提交的远程数据。

也许你应该解释为什么你在考虑这个想法。似乎有一个不同的问题是核心问题。