避免重复提交的Git rebase方法

避免重复提交的Git rebase方法,git,github,version-control,Git,Github,Version Control,当我试图从master重新基址到我的开发分支时,我面临一个奇怪的问题。在master和dev分支中都有一些工作正在进行中 为了从主人那里得到改变,我做了如下的事情 git checkout dev git rebase master 这个很好用。但— 当我执行时,dev分支提交正在重复 git签出开发 git添加。 git commit-m“一些变化” git推送 git重基主控器 在开发分支的git项目历史记录中,提交一些更改正在重复。它还创建循环 如果我在推动开发分支更改之前执行了gi

当我试图从master重新基址到我的开发分支时,我面临一个奇怪的问题。在master和dev分支中都有一些工作正在进行中

为了从主人那里得到改变,我做了如下的事情

git checkout dev
git rebase master
这个很好用。但—

  • 当我执行时,
    dev
    分支提交正在重复
    
    git签出开发
    git添加。
    git commit-m“一些变化”
    git推送
    git重基主控器
    
    在开发分支的git项目历史记录中,提交
    一些更改
    正在重复。它还创建循环
  • 如果我在推动开发分支更改之前执行了git rebase master,那么它工作得很好,我可以在项目中看到线性历史
  • 我不知道为什么会这样。在我看来,这似乎是一种奇怪的行为。如果有人能解释,请帮忙

    项目历史记录 提交
    b48659d
    是重复的(最初的提交我在dev分支中执行了
    37c07a4
    )第一次推送,然后重新基址

    *   fbadb86 (HEAD -> dev) Merge branch 'dev' of *******
    |\  
    | * b48659d (origin/dev) sample added in dev branch --> did rebase after push and got this commit again
    * | 37c07a4 sample added in dev branch --> commit + push
    * | 46c1f40 (origin/master, origin/HEAD, master) master file added in master branch --> commit + push
    |/  
    * 5baae80 first commit
    
    在执行推送之后,所有提交都会发生这种情况。这在重新定基时造成了很多问题,因为提交正在重复,而且即使我自己的代码在以前的提交中发生了更改,也会产生批量冲突。

    所有提交始终是只读的。它们也是永久性的,除了一些例外(与是否有人能找到它们有关)。这意味着
    git-rebase
    复制提交。这就是我的工作

    让我们看看您的
    git日志--graph--oneline…
    输出,但让我们从简单一点开始:

      * b48659d (dev) ...
    * | 46c1f40 (origin/master, origin/HEAD, master) ...
    |/
    * 5baae80 first commit
    
    注意缩短的散列ID,例如
    5baae80
    b48659d
    。这些是每个提交的“真实名称”,缩短为7个字符,因为这通常就足够了。1每个提交记录父提交的ID,Git使用这些父提交哈希值从最近的分支提示提交开始,在历史记录中向后跟踪每个提交。分支
    dev
    的提示提交现在是
    37c07a4…

    5baae80--46c1f40   <-- master, origin/master
           \
            b48659d   <-- dev
    
    此时,您运行了
    git-rebase
    ,这就是开始出错的地方


    1Git现在动态选择缩短的长度,而不是总是使用7,但默认情况下它从7开始。您始终可以使用更多:全名当前有40个字符长


    重基复制提交,然后移动分支标签
    git-rebase
    命令无法更改任何现有的提交,因为git中没有任何东西可以这样做。Git的设计就是为了让这成为不可能。因此,它甚至没有尝试。相反,它复制提交

    复制提交时,Git需要两条信息:

    • 它应该复制什么
    • 它应该把副本放在哪里
    Git通过列出从
    HEAD
    开始向后执行的提交,并在您选择的某个点停止,从而获得要复制的第一个提交列表。(此列表是向后的,因此必须将其反转。)Git从您提供的参数中获取目标“copy after”点的秒数,例如
    master

    在这种情况下,
    HEAD
    names
    dev
    (因为您在启动重基之前运行了
    git checkout dev
    ),因此要复制的提交将以名称
    dev
    指向的副本结束:

    5baae80--46c1f40   <-- master, origin/master
           \
            b48659d   <-- dev (HEAD), origin/dev
    
    既然已经复制了整个提交列表,
    git-rebase
    做了最后一件事。它从原始提交字符串中拉出名称
    dev
    ,并将其粘贴到新副本上。结果是:

                     37c07a4   <-- dev (HEAD)
                    /
    5baae80--46c1f40   <-- master, origin/master
           \
            b48659d   <-- origin/dev
    
    该提交之所以存在,是因为您运行了
    git merge

    您可能通过运行
    git pull
    来运行
    git merge
    。默认情况下,
    git pull
    为您运行
    git fetch
    ,然后为您运行
    git merge
    。(我建议Git初学者千万不要使用
    Git pull
    :它的功能和方式都非常混乱。将它分成
    Git fetch
    ,然后迟早会执行第二个Git命令,有时是
    Git rebase
    ,有时是
    Git merge

    一般来说,
    gitmerge
    所做的是尝试将两条独立的“开发线”结合起来。给出这样一张图:

                     37c07a4   <-- dev (HEAD)
                    /
    5baae80--46c1f40
           \
            b48659d   <-- origin/dev
    
    这就是您现在看到的,在
    git日志--graph--oneline…
    输出中(还添加了
    master
    origin/master
    箭头,因为这样画太难了,所以我把它们省略了)

    这里的基本错误是在别人已经提交的提交上运行
    git-rebase
    。在本例中,位于
    origin
    的另一个Git已经提交了
    b48659d
    。您无法更改该提交,因此,当您创建新副本时,您将停止使用您的
    b48659d
    ,但他们仍然拥有自己的副本。最终,你必须将“他们的”和“你的副本”合并在一起,让这张图片变得相当混乱

    (这条规则有一个例外:如果你能说服所有拥有b48659d的人放弃它,并将他们的
    dev
    s转换为使用你的新副本,你仍然可以重新设置基础。但你是否可以,以及如何做,是另一个问题。)

    所有提交都是只读的,始终如此。它们也是永久性的,除了一些例外(与是否有人能找到它们有关)。这意味着
    git-rebase
    复制提交。这就是我的工作

    让我们看看您的
    git日志--graph--oneline…
    输出,但让我们从简单一点开始:

      * b48659d (dev) ...
    * | 46c1f40 (origin/master, origin/HEAD, master) ...
    |/
    * 5baae80 first commit
    
    注意缩短的散列ID,例如
    5baae80
    b48659d
    。这些是每个提交的“真实名称”,缩短为7个字符,因为这通常就足够了。1每个提交记录父提交的ID,Git使用这些父提交哈希值从最近的分支提示提交开始,在历史记录中向后跟踪每个提交。分支
    dev
    的提示提交是n
    *   fbadb86 (HEAD -> dev) Merge branch 'dev' of *******
    
                     37c07a4   <-- dev (HEAD)
                    /
    5baae80--46c1f40
           \
            b48659d   <-- origin/dev
    
                     37c07a4--fbadb86   <-- dev (HEAD)
                    /         /
    5baae80--46c1f40         /
           \       __--------
            b48659d   <-- origin/dev