看起来你想要两件事:
因此,你想编写一个脚本(将其命名为git-something
并将其放在你的路径上,以便它成为额外的git命令)来识别和处理这些提交。你需要一些触发器让脚本识别本地提交。简单的方法是在提交说明中放置一个魔法词--你永远不会在真实/共享的提交中使用--让脚本识别。(如果这听起来太不可靠了,你也可以在提交的树中使用一个特殊文件,比如.THIS_COMMIT_IS_LOCAL_ONLY
;我没有在示例中使用它,因为它有点难。)
你需要一个命令从当前索引/工作目录创建本地提交;这很容易,它只是调用git commit $@ -m "__LOCAL_COMMIT_ONLY__"
(这是一个示例;重点是它会做一些标记正在创建的提交为本地专用,然后转到git commit)。你还需要一个命令来临时弹出所有本地提交,执行一些其他的git命令(pull、push、fetch、merge等),然后重新应用本地提交。你也将使用这个命令来创建你打算共享的本地提交,以便它们始终出现在你的历史记录中的本地专用提交之下。
下面是一个同时提供这两种功能的脚本示例:
#!/bin/sh
if [[ $1 eq 'new' ]]; then
shift
exec git commit $@ -m "__LOCAL_COMMIT_ONLY__"
elif [[ $1 eq
OLD_HEAD=$(git rev-parse HEAD)
OLD_REAL_HEAD="$(git rev-list HEAD --grep=__LOCAL_COMMIT_ONLY__ | tail -n1)^"
git reset --soft $OLD_REAL_HEAD
git $@
git rebase --onto HEAD $OLD_REAL_HEAD $OLD_HEAD
假设您将脚本命名为
git-local
,则使用
git local new
从索引创建新的本地提交(或者使用
git local new -a
从工作目录中修改的文件创建),使用
git local commit
(遗憾的是名称不太完美)创建一个新的“真实”提交,
git local push
进行推送,
git local pull
进行拉取等操作。
主要缺点是需要您记住大多数命令现在都要加前缀
local
。如果您忘记这样做一次,可能会稍微有些麻烦,但不至于太糟糕——一个快速的
git rebase -i
就可以让您轻松地将本地提交移回顶部,您又可以继续运行了。最大的风险是您意外使用
git push
而不是
git local push
并将所有私有更改发送到上游,这会惹怒所有人。为此,您可能需要编写一个小型封装脚本来代替git本身(将其称为
~/bin/git
并确保
~/bin
在您的路径中)。
#!/bin/sh
if [[ $1 = 'push' ]]; then
if /usr/bin/git rev-list HEAD --grep=__LOCAL_COMMIT_ONLY__ | grep -q .; then
echo "Can't push with local changes still active!"
echo "Try using `git local push' instead."
exit 1
fi
fi
exec /usr/bin/git "$@"
您还可以在服务器上创建一个
pre-receive
钩子,自动拒绝任何提交消息中包含
__LOCAL_COMMIT_ONLY__
的提交。