我想使用git来保存应用程序随时间使用的实际依赖关系的历史记录,其保真度高于我从包管理器获得的保真度。
我正在使用这些分支:
.gitignore
这个脚本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
哪个有效,并且让我对从一个版本到下一个版本的源,依赖项和二进制文件的更改有用的看法:
但它需要的提交次数是必要的两倍。我希望树看起来像这样:
如何组合"复制内置文件"提交"构建为"提交?
当我尝试git merge --squash
时,它会以build
上的状态而不是build-$TIMESTAMP
上的状态结束,这是不正确的(我想将更改导入到忽略文件,但合并似乎没有语言可以做到这一点)。当我尝试git rebase --onto build build-$TIMESTAMP
时,我失去了新提交的父母身份。
我只想记录build-$TIMESTAMP
分支上的确切文件,但同时将build
和master
分支作为父级,然后指向build
分支那个提交。
答案 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-tree
和git write-tree
的极其薄的包装,主要的额外操作是提供HEAD
作为父级和tu opdate HEAD
到新的提交。名称HEAD
本身就是传统的。构建这些内容跟踪器的内容跟踪器不太关心HEAD
,或者分支和标签之间的区别,或者任何类型的区别。这些约定是有意,积极和残酷的简单,因为(a)不需要抽象,内容模型已完全符合要求,(b)git的重点在于核心缺乏抽象:它"愚蠢"。
答案 1 :(得分:0)
在我看来,最好的解决方案是改变你在这里使用git的方式。 Git是一个版本控制系统,用于跟踪文件随时间的变化。由于您经常添加和删除文件,因此您将丢失它并将其用作文件存储。那么,为什么不使用文件存储。我认为你的解决方案很聪明,但它让我感到气味,就像你在“对抗框架”一样。
我认为如果您想保留已构建文件和实际依赖项的记录,最好将所有内容压缩并将其存档到构建过程的一部分。