【问题标题】:Git: Preserving current code state and last four commitsGit:保留当前代码状态和​​最后四次提交
【发布时间】:2018-07-24 11:22:30
【问题描述】:

请注意:这个问题与Squash my last X commits together using Git 不同,因为我们不希望将最后一个 X 提交一起压缩成一个提交 - 相反,我们希望初始提交合并为一个提交并以自动方式保留最后四个提交/代码状态(无需手动选择提交) .

我们正在使用 git 备份/记录对文件数据存储的更改,该更改使用内部托管的 GitLab 服务器,其存储库包含一些非常大的文件。

我们想合并早期的冗余提交,这些提交不再需要减少 repo 的大小,但 保持当前代码状态和​​最后四个提交为备份以防我们需要将数据存储恢复到以前的提交。

自动化脚本中推荐哪些命令会改变以下 git 历史记录:

0    aabbcc Initial commit
1    aabbdd First backup
2    aabbee Second backup
3    aabbff Third backup
4    aabbgg Fourth backup
5    aabbhh Fifth backup
6    aabbii Sixth backup
7    aabbjj Seventh backup (current code state)

变成以下不丢失当前代码状态

4    aabbgg Initial commit -> Fourth backup (consolidated)
5    aabbhh Fifth backup
6    aabbii Sixth backup
7    aabbjj Seventh backup (current code state)

【问题讨论】:

  • 为什么你认为你可以在不改变代码状态的情况下删除前 4 个提交?这是不可能的,很有可能。
  • @TimBiegeleisen 我们需要将所有以前的提交合并到一个提交中,但保留最后四个提交.. 这对于 git 来说是不可能的吗?
  • @TimBiegeleisen 这个问题与标记为重复的问题不同,因为我们希望将我们的初始提交合并到一个提交并自动保持最后四个提交,而建议的重复问题的答案解释了如何压缩最后一次提交而不是初始提交,并且需要手动用户输入。
  • git checkout aabbgg && git reset --soft aabbcc^ && git commit -m "Initial commit -> Fourth backup (consolidated)" && git tag new_base && git checkout -b consolidated master && git rebase --onto new_base aabbgg
  • @Steve 我之前提到的重复链接或 Serge 的软重置方法基本上是压缩提交的两种方法。但是,一般来说,两者都可能需要人工干预。

标签: git gitlab


【解决方案1】:

可能是这样的。

首先,压缩旧的提交:

git checkout aabbgg         # checkout the commit that you want to squash the older commits into
git reset --soft aabbcc^    # squash the commits...
git commit -m "Initial commit -> Fourth backup (consolidated)"
git tag new_base            # tag it, we will use the tag later

接下来,将较新的提交重新定位到新的基础上:

git checkout -b consolidated current_code_state
git rebase --onto new_base aabbgg

注意:为避免rebase 在冲突中停止,您可能需要指定合并策略,例如:

-s recursive -X ours -X no-renames

结果:

x - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 (current_code_state)
 \
  4' (new_base) - 5' - 6' - 7' (consolidated)

current_code_stateconsolidated 之间应该没有区别。

最后,如果一切顺利,删除原来的分支和之前创建的标签。

git branch -D current_code_state
git tag -d new_base

【讨论】:

  • ^ 字符是必需的吗?运行以下命令时出现问题:git reset --soft aabbcc^ 但可以通过省略 ^ 成功运行。根据您的答案编写自动化脚本几乎已完成 - 将尽快发布。非常感谢
  • ^ 表示“它的父级”。但是,如果 aabbcc 是第一个提交,则它没有父提交。
【解决方案2】:

根据 sergej 的回答 (Git: Preserving current code state and last four commits),我编写了一个似乎可以正常工作的自动化脚本:

#!/bin/bash

function gitConsolidation() {

    # Default settings
    numCommitsToKeep=4
    branchName="master"
    path="/home/steve/test/testgit"

    # Set working directory
    cd $path

    # Get git repo name
    gitRepoName=$(basename `git rev-parse --show-toplevel`)

    # Print default message
    echo -e "** Prepairing to consolidate current Git Repo: $gitRepoName **"
    echo -e "Branch: $branchName"
    echo -e "Path: $path"
    echo -e "Total past commits to keep: $numCommitsToKeep\n"

    # Get required branch
    git checkout $branchName

    # Get size before consolidation
    echo -e "Repo size before consolidation: $(du -hs)" 

    # Print current log list
    echo -e "\n* Git commits prior to consolidation *"  
    git log --pretty="%H - %s"

    # Get initial commit hash
    initialCommitHash=$(git rev-list --max-parents=0 HEAD)
    echo -e "\n* Found initial commit hash: $initialCommitHash *"

    # Get hash for commit to be consolidated with intiial commit
    consCommitHash=$(git log --format=%H | head -$numCommitsToKeep | tail     -1)
    echo -e "* Found hash for commit to consolidate with initial commit: $consCommitHash *"

    # Get hash for latest commit
    latestCommitHash=$(git log --format=%H | head -1)
    echo -e "* Found hash for latest commit $latestCommitHash *\n"

    # Begin consolidation
    echo -e "* BEGIN: Git repo consolidation *"

    # Checkout commit to consolidate with initial commit
    git checkout $consCommitHash

    # Soft reset initial commit
    git reset --soft $initialCommitHash

    # Commit changes
    git commit -m "Consolidated commit $initialCommitHash -> $consCommitHash"

    # Set tag
    git tag new_base

    # Checkout
    git checkout -b consolidated $latestCommitHash

    # Rebase
    git rebase --onto new_base $consCommitHash

    # Get size after consolidation
    echo -e "Repo size after consolidation: $(du -hs)"

    # Print current log list
    echo -e "\n * Git commits after consolidation *"    
    git log --pretty="%H - %s"

    echo -e "\n* END: Git repo consolidation *"
}

# Call function
gitConsolidation

已在本地测试存储库上成功运行。即将在我们的大型存储库的副本上进行测试,看看是否可以正常工作!

【讨论】:

  • 虽然您可以让 Git 执行此操作(您的脚本看起来可行),但您应该注意您所做的相当于使用源代码管理系统作为备份系统。 SCM 不是作为备份系统设计的(反之亦然),这就是为什么它像这样相对痛苦。一个设计良好的备份系统将使保存 N 个备份(对于任何合适的 N 个)变得非常干净和简单。在我长期停滞不前的book 的第一章中,我还有一些关于备份与 SCM 的说明。
  • @torek 同意 - 不幸的是,由于他们的开发工作流程,这是客户的要求 - 其中包括许多依赖于应用程序代码并且必须与应用程序的版本控制同步的大型数据文件代码。还有一个独立的备份系统用于将环境备份到 Veeam 快照/磁带驱动器;)
猜你喜欢
  • 1970-01-01
  • 2017-06-21
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 2015-04-09
  • 2020-12-11
  • 2013-05-27
相关资源
最近更新 更多