【发布时间】:2012-10-20 09:12:55
【问题描述】:
在过去的几个月里,我不小心把我的 umask 设置错误了,不知何故没有注意到。
我的一个 git 存储库有许多标记为可执行文件的文件,应该只有 644。这个 repo 有一个主 master 分支和大约 4 个私有功能分支(我一直在 master 之上重新建立)。
我已经通过运行find -type f -exec chmod 644 {} \; 并提交更改来更正了我的主分支中的文件。然后我将我的功能分支重新定位到 master 上。
问题是特性分支中有新创建的文件仅在该分支中,因此我的大量 chmod 提交没有更正它们。我不想为每个功能分支创建一个与我在 master 上所做的提交相同的事情的新提交。所以我决定最好回到每个提交文件的地方并设置权限。
这是我尝试过的:
git filter-branch -f --tree-filter 'chmod 644 `git show --diff-filter=ACR --pretty="format:" --name-only $GIT_COMMIT`; git add .' master..
看起来这很有效,但经过进一步检查,我注意到在包含具有适当权限 644 的新文件的提交之后的每个提交实际上都会通过以下方式恢复更改:
diff --git a b
old mode 100644
new mode 100755
我一生都无法弄清楚为什么会发生这种情况。我想我一定是误解了git filter-branch 的工作原理。
我的解决方案
我已经使用这个命令解决了我的问题:
git filter-branch -f --tree-filter 'FILES="$FILES "`git show --diff-filter=ACMR --pretty="format:" --name-only $GIT_COMMIT`; chmod 644 $FILES; true' development..
我不断添加到 FILES 变量中,以确保在每次提交中,在某个时间点创建的任何文件都具有正确的模式。
然而,我仍然不确定我是否真的理解为什么 git 会跟踪 each 提交的文件模式。我虽然在第一次创建文件时已经修复了文件的模式,但它会保持该模式,除非我的其他提交中的一个显式将其更改为其他内容。情况似乎并非如此。
我认为这会起作用的原因是我对rebase的理解。如果我回到HEAD~5 并更改一行代码,该更改会传播,它不会只是在HEAD~4 中更改回来。
【问题讨论】:
-
filter-branch不是rebase。filter-branch带有树过滤器只会更改每次提交中的树。rebase重播每个重新提交的提交引入的更改。我不确定您对 filter-branch 的期望。 -
@CharlesBailey 我对
fitler-branch --tree-filter的理解是,在这个过程中,如果对工作目录进行任何更改,那么该更改将导致进行新的提交。然后必须在其上重放子提交。那么为什么它不像变基一样呢? -
是的,使用树形过滤器,所有更改都对正在更改的提交进行。然后将树重置为下一次提交的状态。如果该文件在下一次提交中是原始可执行文件,那么它将在树中可执行。除非您专门删除过滤器中的可执行文件,否则它将保持可执行。通过使用
git show来确定文件列表,您只是删除了最初触及文件的提交中的可执行位。在未触及文件的提交中,您没有删除可执行位。
标签: git unix chmod git-filter-branch