如何设置Git分支进行自动备份

如何设置Git分支进行自动备份,git,version-control,merge,backup,Git,Version Control,Merge,Backup,我意识到已经有关于如何备份存储库的问题了(答案通常是git bundle),但我不知道具体的设置 我会尝试定期将当前分支的“快照”提交给另一个分支以进行备份。我使用的是一个批处理文件,看起来是这样的(我尝试了比这里列出的更多的变体): 我的目标是,无论我在运行时签出了哪个分支,每次提交都应该是目录当前状态的精确快照。如果较新的提交更改了文件,我希望在出现合并冲突时它优先 实际上,我并没有尝试合并分支,我只是尝试获取磁盘上快照时存在的文件。因此,如果分支A对文件A有更改,而分支B对同一文件有冲突的

我意识到已经有关于如何备份存储库的问题了(答案通常是
git bundle
),但我不知道具体的设置

我会尝试定期将当前分支的“快照”提交给另一个分支以进行备份。我使用的是一个批处理文件,看起来是这样的(我尝试了比这里列出的更多的变体):

我的目标是,无论我在运行时签出了哪个分支,每次提交都应该是目录当前状态的精确快照。如果较新的提交更改了文件,我希望在出现合并冲突时它优先

实际上,我并没有尝试合并分支,我只是尝试获取磁盘上快照时存在的文件。因此,如果分支A对文件A有更改,而分支B对同一文件有冲突的更改,但分支B已签出,则备份分支应最终获得分支B的更改,这些更改当前位于磁盘上的文件中,而忽略任何其他更改

还有一个实际的(?)例子,说明我正在尝试做的事情: 假设分支A的“myfile.txt”为“Hello World”,分支B的“myfile.txt”为“Hello Dave”

当我签出分支A并在文本编辑器中打开“myfile.txt”时,我希望它会有“Hello World”。当我签出B时,我希望它有“你好,戴夫”

如果在一个分支中,commit 1有“helloworld”,而2有“hellowdave”,那么就不会有冲突。我希望我的备份分支以包含“Hello World”的commit 1和包含“Hello Dave”的commit 2结束,假设commit 1发生在我之前签出分支A时,而分支B发生在commit 2时

我相信git stash是我所做工作的关键,但它根本不起作用。我尝试了这些命令的几种不同组合,当repo处于不同状态时,它们在不同的点上返回了不同的错误变体,因此很难对它们进行总结。我想说我的方法可能根本上是错误的,所以这里列出的命令只是为了展示我迄今为止所做的尝试


但无论我做什么,我要么得到合并冲突,要么什么都没有提交。我错过了什么?(如果我能提供任何其他信息,请让我知道)

问题是您试图让git假装您的所有分支都可以在单个分支中共存(您称之为备份)。因此,实际上,您正在合并所有内容,很自然,您会遇到冲突

为了澄清,这里有一个例子: 分支a的文件f包含文本“a”,分支b的文件f包含文本“b”。在分支a上工作时,会发生自动备份,并在备份分支中存储f=“a”。然后,无论出于何种原因,您在分支b上工作,并进行自动备份,现在您正在尝试存储f=“b”。这是一个合并冲突,因为分支a和b之间没有关系(可能它们都从prod分支继承了文件f,其中文件f包含“prod”,并将其分别更改为“a”和“b”)

如果要在给定时间拍摄目录中内容的快照,则需要使用标记,并且可能需要将标记的拍摄时间作为标记名的一部分,例如workdir-snapshot-20140818-1432


请记住,分支只是指向提交的指针,因此使用术语“备份”确实会产生误导,您实际上不是在备份数据,您要跟踪的最多的是在给定时间将哪个分支签出到您的workdir,就是这样。

问题在于,您试图让git假装您的所有分支都可以在单个分支中共存(您称之为备份)。因此,实际上,您正在合并所有内容,很自然,您会遇到冲突

为了澄清,这里有一个例子: 分支a的文件f包含文本“a”,分支b的文件f包含文本“b”。在分支a上工作时,会发生自动备份,并在备份分支中存储f=“a”。然后,无论出于何种原因,您在分支b上工作,并进行自动备份,现在您正在尝试存储f=“b”。这是一个合并冲突,因为分支a和b之间没有关系(可能它们都从prod分支继承了文件f,其中文件f包含“prod”,并将其分别更改为“a”和“b”)

如果要在给定时间拍摄目录中内容的快照,则需要使用标记,并且可能需要将标记的拍摄时间作为标记名的一部分,例如workdir-snapshot-20140818-1432


请记住,分支只是指向提交的指针,因此使用术语“备份”确实有误导性,您实际上不是在备份数据,您要跟踪的最多的是在给定时间哪个分支签出到您的workdir,就是这样。

我无法理解您为什么需要这样做。

您可以使用git config core.logAllRefUpdates true。这将使git保持每个分支所在位置的完美历史。您甚至可以调整它,使其永不过期,您将拥有每个分支的完美历史记录(而不仅仅是当您记得备份它时)


如果你真的想这样做你可以让索引包含你想要的树,然后提交它

  • 切换到备份分支
    git stash;git签出备份
  • 清除索引
    git rm-fr--cached.
  • 将要备份的提交的目录树复制到索引中
    git ls tree branchA | git update index--index info
  • 提交结果
    git提交-m“branchA备份”
    (不要使用
    -a
    !)
  • 回到您来自的地方
    git checkout-f branchB;git隐藏流行音乐
    。您需要使用
    -f
    ,因为工作副本会说它脏了
  • 这将永远不会有任何合并冲突,因为您没有合并任何内容。
    git stash
    git checkout backup
    git add .
    git commit -m "Automatic Backup  %Time%"  
    git push --all origin
    git stash pop
    git checkout -
    
    $ mkdir example
    $ cd example
    $ git init
    Initialized empty Git repository in /tmp/example/.git/
    $ echo "First change" > file1
    $ git add file1
    $ git commit -am "file1 first change"
    [master (root-commit) f071d01] file1 first change
     1 file changed, 1 insertion(+)
     create mode 100644 file1
    $ git branch master_two
    $ git checkout master_two
    Switched to branch 'master_two'
    $ sed -i s/First/Two/g file1·
    $ git commit -am "Two change"
    [master_two b786d88] Two change
     1 file changed, 1 insertion(+), 1 deletion(-)
    $ git checkout master
    Switched to branch 'master'
    $ sed -i s/First/Second/g file1
    $ git commit -am "Second change"
    [master d88ca84] Second change
     1 file changed, 1 insertion(+), 1 deletion(-)
    $ git checkout --orphan backup
    Switched to a new branch 'backup'
    $ git rm -fr --cached .
    rm 'file1'
    $ git ls-tree master | git update-index --index-info
    $ git commit -am "snapshot of master"
    [backup (root-commit) 7af271d] snapshot of master
     1 file changed, 1 insertion(+)
     create mode 100644 file1
    $ git rm -fr --cached .
    rm 'file1'
    $ git ls-tree master_two  | git update-index --index-info
    $ git commit -m "snapshot of master_two"
    [backup a3ddfdd] snapshot of master_two
     1 file changed, 1 insertion(+), 1 deletion(-)
    $ git checkout -f master
    Switched to branch 'master'
    
    #!/bin/bash
    BRANCH=backup
    export GIT_INDEX_FILE=/tmp/git-backup-index.$$
    git add .
    git commit-tree $(git write-tree) -p $(git show-ref --hash --heads $BRANCH) -m "Automatic backup" | xargs git branch -f $BRANCH
    rm -f "$GIT_INDEX_FILE"