由git subtree/submodule 引发的关于git hook 的解决方案

        最近在学习objc_runtime源码这部分的内容需要写一些笔记,看源码的仓库加入自己的一些笔记,但是看源码的仓库有很多一些关于runtime相关的代码还有前辈朋哥的笔记。我想要把笔记抽出来作为子仓库,同时想要在主仓库里面也留着笔记。

仓库图

1、submodule方案

        最常见的办法就是把子仓库作为主仓库的子模块,好有想法直接开搞。我马上就添加子模块,提交代码,发现在主模块中每次提交都不会获知当前子模块修改提交的内容,只会留下一句commit XXXXXX。


submodule方案

        如果主仓库不关注子仓库的变化的话,可以使用这个方案,但是我关注呀!有时候我又想在主仓库看看我之前提交的内容,GitHub上也看不了,只能看到Submodule XXX。如果这样的话,在GitHub上看不到具体的内容,要拉去代码才能看到里面的内容,岂不是给搜索引擎们缺少(扫)了个机会?可不行,万一我想去GitHub上看看自己的笔记可不是没得谈。

如果是子模块GitHub中显示状态

2、subtree方案

        我就想那我就使用subtree的方式。subtree相当于成为主仓库的一个子项目一样,可以看到变更修改所有操作,也可以推上去到主仓库里(具体的subtree的使用已经很多文章介绍到了)。subtree有个缺点,我个人认为的缺点,就是推拉子项目的时候,出现莫名其妙的冲突和无更新内容???

sourcetree 拉取到的内容显示
推送失败的内容

        主仓库就的README.md和子仓库的README.md大家的路径不一样,为什么你就窜味了呢?再者我明明就有修改 为什么推送出现问题。

3、第三个猜想---subtree与submodule的结合体?

        因为结合嘛如果想要同时显示和提交,那么有subtree来进行显示以及主仓库管理子项目中文件,submodule来负责提交更新到我们的子仓库中。

        当然不行,还有这么玩? 因为我们需要同一个路径处理(因为我们改的子仓库内容肯定只有一个地方,难道要两份地方改了这边复制过去?不适合我们计算机仔的逻辑操作)。那么同一个路径的话,当我们加入后者(submodule)时候 ;就会提示改路径已经存在Index重复,我尝试直接在.gitmodules文件中加入无法识别出commit XX(如上submodule方案图) 那么还是无法提交的。

4、第四个猜想---subtree与git hook结合体   

        思路来源:由于一开始的想抽离笔记为另一个仓库同时又保留在主仓库这个想法,寻求解决方案,第一第二个方案都不完美,第三个方案想法很完美 但是不能完全的实现。所以就想着用subtree方案为基础,我把子仓库的.git文件复制进去不就好了?接着主仓库(子仓库在这里相当于一个文件夹)尽管提交,到时候手动的去提交子仓库。我突然想起不是hook这个东西,好家伙git有个hooks。我直接hook 到主仓库commit的时机在此,偷偷在后面提交和推送子仓库,做到神不知鬼不觉。

关于git hook

            本次我用到的三个脚本,分别是pre-commit、commit-msg、post-commit;

            一开始只是使用到了commit-msg想着在提交的时候,就提交以及推送子仓库的内容。(基本完成了简单我的想法)但是问题来了,难道以后大家要用到这个的时候,专门去找到子仓库的.git文件,接着复制到对应的位置,接着开始,添加commit-msg的内容。这不麻烦吗?可不嘛!所以我开始麻烦自己了,可不可以把.git文件打包成一个压缩包,接着对子仓库是不可见的,对主仓库可见;当主仓库进行提交操作之前,就把其解压出来放好在对应位置,接着就开始提交子仓库的内容。

        为什么主仓库可见,因为我们每次都要更新一下子仓库的.git文件(.git文件是在git不可识别的/忽略的,所以主仓库中也是无法识别的,才有了压缩包这个想法)。

          怎么做到呢?

          第一 在主仓库提交的时候 把子仓库提交并且推送 。

                  子仓库完成了提交和推送之后的.git文件此时可以进行压缩保存

                  为提交到主仓库中作准备

          第二 主仓库提交了的内容 必须回滚回来上一个阶段(混合回滚 保留原有修改)

                  因为我这里要把子仓库上次提交的.git压缩包 提交到主仓库中。

          第三 推送主仓库的内容。


第一步

        第一步 中产生了我们的子仓库.git 压缩包,我们在commit主仓库的时候已经提交上去了 但是我们还没推送 还有话好说,所以我们就需要一个精髓的操作----回滚上一个阶段。

        第二步 我们才真正的把我们的修改内容(来源上一步回滚)和.git包一起提交上去

第二步

          涉及两个中间变量TEMPVAR、TEMPCOMMITMSG,向.git学习 它就是用这个文件来存储提交的信息,所以我也有两个中间变量,我用完之后还删除了,嘻嘻。

文件1


内容

GitHub:https://github.com/pirder/StudyNotes_Objc


直接贴码:

pre-commit:提交前

#!/bin/sh

#一开始默认是没有.git 必有git压缩包

#没有git 解压.git

fileName="./阅读笔记/StudyNotes"

cd "$fileName"

ls .git &> /dev/null || {

  tar -xvf subtreeGit.tar.gz &> /dev/null || {

      echo "没有子仓库的.git 也没有 .git 的压缩包"

  }

}

commit-msg:提交中

#!/bin/sh

# ===== 在commit 主仓库时候 就可以如果子仓库有改动就可以把子仓库的提交并且推送了

echo "======提交之前"

mssageFile="./阅读笔记/StudyNotes/TEMPCOMMITMSG"

fileName="./阅读笔记/StudyNotes/TEMPVAR"

TAGCOMMITFIRS=$(cat $fileName || {

    ##确保之前就存在

    touch $fileName

    echo "true" > $fileName

    })

TAGCOMMITFIRS=$(cat $fileName)

#第一次 提交tag 为true 非第一次 tag 为false

if $TAGCOMMITFIRS

then

echo "进入 第一次的子库提交"

else

echo "提前结束"

exit 0

fi

commitMessage=$(cat "$1")

hasCommitCommand=true

echo "信息描述为 $commitMessage"

##确保之前就存在

touch $mssageFile

#存起来我们提交的msg

echo $commitMessage > $mssageFile

#处理子仓库 提交

cd ./阅读笔记/StudyNotes

git add -A

git pull origin main #解压出来的git 防止存在版本偏差 先进行拉取

git commit -m "$commitMessage" || {

echo "子仓库无commit或者在上一次已经提交了"

hasCommitCommand=false

}

#如果有提交内容 就进行推送 并且打包好推送完成的.git文件

if $hasCommitCommand

then

echo "子仓库开始push"

git push origin main || {

    echo  "子仓库推送失败"

}

echo "把子仓库的.git打包起来 接着删除存在的 并且在进行解压"

#对于子仓库应该是不知他的存在 在主仓库存在

tar -zcvf subtreeGit.tar.gz .git &> /dev/null

fi

post-commit:提交后

#!/bin/sh

# ===== 在commit 主仓库时候 就可以如果子仓库有改动就可以把子仓库的提交并且推送了

# 子仓库提交完成之后 主仓库回滚 到上一次提交 把.git 压缩起来提交 以后都能使用 可以在提交前hook把其解压出来

echo "======提交之后"

##中间变量记录主仓库第几次提交

fileName="./阅读笔记/StudyNotes/TEMPVAR"

##记录中间消息内容

mssageFile="./阅读笔记/StudyNotes/TEMPCOMMITMSG"

TAGCOMMITFIRS=$(cat $fileName || {

    echo "true" > $fileName

    })

TAGCOMMITFIRS=$(cat $fileName)

echo $TAGCOMMITFIRS

if $TAGCOMMITFIRS

then

#回滚之前第一次主仓库提交

git reset --mixed master^

TAGCOMMITFIRS=false

echo $TAGCOMMITFIRS > $fileName

echo "====第一个提交 负责处理子仓库中的提交 和 推送"

git add -A

commitMsg=$(cat $mssageFile)

#这才是真正的提交

git commit -m "$commitMsg"

else

#移除中间文件

echo "移除临时中间文件"

rm -r $fileName

rm -r $mssageFile

echo "====结束所有流程"

fi

你可能感兴趣的:(由git subtree/submodule 引发的关于git hook 的解决方案)