Git - 如何在不丢失这些更改的情况下将更改压缩到忽略的文件?

时间:2014-07-31 11:22:45

标签: git

我想使用git来保存应用程序随时间使用的实际依赖关系的历史记录,其保真度高于我从包管理器获得的保真度。

我正在使用这些分支:

  • master:仅限源代码。 .gitignore
  • 中的依赖项
  • 构建:源代码和依赖项
  • build- $ TIMESTAMP:用于强制提交被忽略文件的临时分支

这个脚本build-release.sh

DEV_MODULES="mocha chai bower coffeelint"
BUILT_FILES="node_modules build"
DATE=$(date)
TIMESTAMP=$(date +"%s")
BRANCH=$(git rev-parse --abbrev-ref HEAD)

# create a temporary branch with the current dependencies and binaries
npm uninstall $DEV_MODULES
git checkout -b build-$TIMESTAMP
git add --all --force $BUILT_FILES
git commit -m "copy $BUILT_FILES from $BRANCH"

# merge the temporary branch into the build branch
git branch build || echo "build branch already exists"
git checkout build --force
git merge build-$TIMESTAMP --strategy=subtree -m "Build as of $DATE"
git branch -D build-$TIMESTAMP

# restore the original branch
git checkout $BRANCH
git checkout build -- $BUILT_FILES
git rm -r --cached $BUILT_FILES

哪个有效,并且让我对从一个版本到下一个版本的源,依赖项和二进制文件的更改有用的看法:

Screenshot showing merge bubbles

但它需要的提交次数是必要的两倍。我希望树看起来像这样:

artist's concept

如何组合"复制内置文件"提交"构建为"提交?

当我尝试git merge --squash时,它会以build上的状态而不是build-$TIMESTAMP上的状态结束,这是不正确的(我想将更改导入到忽略文件,但合并似乎没有语言可以做到这一点)。当我尝试git rebase --onto build build-$TIMESTAMP时,我失去了新提交的父母身份。

我只想记录build-$TIMESTAMP分支上的确切文件,但同时将buildmaster分支作为父级,然后指向build分支那个提交。

2 个答案:

答案 0 :(得分:3)

这是一个简单的管道领域。你正在使用"瓷器"命令,源代码控制系统建立在git的内容跟踪器核心之上,其方式碰巧使瓷器变成你想要的东西,但与内容跟踪器交谈要简单得多直接

最简单地阅读你问题中的内容,即你想要你的" build"分支记录当前结账的快照以及"$BUILT_FILES"路径/目录中的选项,

# knobs
DEV_MODULES="mocha chai bower coffeelint"
BUILT_FILES="node_modules build"
DATE=$(date)

# clean out stuff we don't care about
npm uninstall $DEV_MODULES

# record current checkout plus "$BUILT_FILES" to `build` branch
git add --all --force $BUILT_FILES
build=`git rev-parse -q --verify build`
git update-ref refs/heads/build $(
        git commit-tree ${build:+-p $build} -p HEAD \
                -m "build as of $DATE" \
                `git write-tree`
)

# reset index to HEAD
git reset  # `git read-tree HEAD` will have the same effect, perhaps more quietly

作为案例的快速概述或提醒,git的对象数据库是一个哈希码索引的键值存储。你可以通过它的类型和哈希来询问git的任何内容,它必须从它的对象db中完全回流。索引只不过是一个平面文件,一个路径索引清单,显示对象数据库中的哪些内容在哪个路径上,以及一些元数据和用于跟踪飞行中操作的注释。路径中的git add内容只是将内容放在对象db中,将内容的散列放在该路径的索引条目中。

(在这里有些咆哮,如果没有心情可以跳过,请跳过)要明白的是,git是完全的,残酷的具体。关于对象db之外的存储库的所有内容都是纯粹的约定。 git checkout使HEAD引用您完全按惯例检出的提交。您可以将git checkout实现为git read-tree -um周围非常薄的包装器 - 主要的额外操作是将HEAD设置为您从该树获取的提交。 git commit使HEAD成为您按照惯例纯粹提交的内容。您可以自己实施git commit作为围绕git commit-treegit write-tree的极其薄的包装,主要的额外操作是提供HEAD作为父级和tu opdate HEAD到新的提交。名称HEAD本身就是传统的。构建这些内容跟踪器的内容跟踪器不太关心HEAD,或者分支和标签之间的区别,或者任何类型的区别。这些约定是有意,积极和残酷的简单,因为(a)不需要抽象,内容模型已完全符合要求,(b)git的重点在于核心缺乏抽象:它"愚蠢"。

答案 1 :(得分:0)

在我看来,最好的解决方案是改变你在这里使用git的方式。 Git是一个版本控制系统,用于跟踪文件随时间的变化。由于您经常添加和删除文件,因此您将丢失它并将其用作文件存储。那么,为什么不使用文件存储。我认为你的解决方案很聪明,但它让我感到气味,就像你在“对抗框架”一样。

我认为如果您想保留已构建文件和实际依赖项的记录,最好将所有内容压缩并将其存档到构建过程的一部分。