- 创建新的远程repo
- github更新
- git本地配置
- 快速解决conflic
- git submodule使用
- 抹掉本地和远程上的commit
- fetch远程分支
- 修改.gitignore生效
- 创建并上传远程仓库
- clone仓库的某个tag版本
- 打tag并push到github
- 查找 git log
- 回退linux内核到某个tag
- 从Github上clone仓库到本地
- 追溯ffmpeg最新版本修复内存泄露的版本
- 查看某个文件某个历史版本的内容
- 远程仓库控制问题
记录开发中实际涉及的Git知识
创建新的远程repo
场景:你在本地编码了一部分代码,现在准备push到远程的新repo中,然后你先创建了一个repo,在创建的时候自动添加了gitignore, readme.md liscens等文件,然后你在本地git init . , git add ., git remote add origin xxx, 最后你想git pull origin master 合入远程repo的内容,却发现提示错误fatal: refusing to merge unrelated histories.
解决办法, git pull origin master --allow-unrelated-histories
github更新
在你fork别人的某个仓库后,如何在一段时间后将你的fork仓库同步别人仓库的所有更新呢? 在github网页上只能通过pull request -> switch base -> new pull去同步某个分支,对于别人新建的tag,则无法同步。 下面是完全同步别人仓库所有分支和tag的步骤,假设我们已经在本地clone了自己仓库的代码:
git remote add upstream https://github/other_peeople/xx
git fetch upstream
git rebase upstream/master
git push
git push --tags
git本地配置
记住账号密码
- gti config --global crendtial.helper store
快速解决conflic
假如在Merge前我们就已经知道会有conflic并且知道全部使用合入的分支代码,或者是全部是本地的代码,那么可以执行:
git checkout --theirs filename.c 或者 git checkout --ours filename.c
然后执行:
git add filename.c
git submodule使用
使用git submodule add https://github.com/xxxx <destination_foler>添加submodule后,会在根目录下生成.gitmodules文件。后续的一些git submodule有些必须在根目录下执行才会生效。
- git submodule status-> 查看当前submodule信息
- git submodule update --init --recursive-> git clone下来的仓库是不会主动将submodule内容checkout下来的,所以需要执行这条命令把所有submoduel都checkout到本地。
- git submodule update --recursive --remote-> 上面一条命令不会checkout最新的commit,需要执行这条拉取submodule对应仓库的最新代码。
上面这些命令只有在存在.gitmodules目录下执行才work。
更新submodule的url
国内访问github已经慢的令人发指,再迁移到gitee上来时必然涉及到submodule的切换。
- 首先直接编辑修改.gitmodules里面的url信息。
- 然后执行git submodule sync将更改信息同步到.git中去
- 最后执行git submoudle update --init xxx即可,如果是同时更新所有submodule,则xxx就是--recursive
切换某个submodule仓库到指定分支
一个常见需求是我们需要切换某个submodule仓库的分支,首先在.gitmodules目录下执行:
- git config -f .gitmodules submodule.api.app.moniter_backend.branch feature/mqtt添加分支信息,执行这个命令后可以在.gitmodules文件里面看到新加的branch信息。命令中的- api.app.moniter_backend就是submodule路径,- moniter_backend是对应的仓库名,- feature/mqtt是该仓库的一个已存在分支。 然后cd到moniter_backend目录下,执行:
- git checkout -b feature/mqtt --track origin/feature/mqtt这样就切换到了- feature/mqtt分支上了。 最后返回到根目录,提交所有操作submodule的改动。
日常操作
当你执行git pull origin master正常更新主仓库,这时执行git status发现出现submodule提示(new commits)的话,说明远程仓库上对submodule有更新,这时你得执行git submodule update --recursive进行同步,不然等你修改主仓库代码后执行git add .或者git add 提示(new commtis)的那个仓库的话,会导致你提交的commit会将remote的submodule又恢复到老版本。
抹掉本地和远程上的commit
如果你想撤销并且不需要保留本地的最新近一次的commit,你可以执行git reset --hard HEAD~1抹掉本地的这个最新commit,而且如果这个commit已经被你提交到了remote,并且你确定remote上么有更新的commit,那么可以执行git push -f origin master抹掉remote上的这个commit
fetch远程分支
如果远程有多个分支,我们如何在本地建立相应的分支去对应track呢?
首先使用git branch -r查看远程分支,假设我们需要track远程上的dec分支,则
- git fetch origin dev
- git checkout -b newbranch origin/dev
上面的newbranch是自定义的分支名,执行成功后,会看到如下log。
Branch ‘newbranch’ set up to track remote branch ‘dev’ from ‘origin’.
修改.gitignore生效
如果中途修改.gitignore并使其立即生效,需要执行
- git rm -r –cached .
- git add .
- git commit -m “xxx”
创建并上传远程仓库
假设现在在本地有一个git仓库带同步到远程仓库。
- 
    在github上创建好一个空的仓库,假设仓库地址为 https://abcd.github.efg.com/saiyn/foo,这种地址可以看出是企业的私有仓库。
- 
    执行 git remote add origin https://abcd.github.efg.com/saiyn/foo添加远程仓库信息。
- 
    执行 git remote -v查看刚刚添加是否正常。
- 
    执行 git pull origin master先拉取远程仓库中的版本信息,同步版本。可能会出现一些冲突需要merge。
如果在github上已经勾选添加README文件的话,进行pull或出现
fatal: refusing to merge unrelated histories错误,这时需要执行git pull --allow-unrelated-histories origin master
- 执行git push origin master将本地仓库推送到远程仓库。
clone仓库的某个tag版本
有时我们需要源码安装github上某个仓库的某个tag版本,首先是在我们正常执行git clone git@github.com:xxx/yyy.git clone仓库yyy到本地.
然后执行git tag -l查看一下有哪些tag版本。
最后执行git checkout tags/zzz从最新版本master分支切换打zzz版本上,切换后的分支默认为(HEAD detached at zzz).

打tag并push到github
- git tag v1.0.1
- git push origin v1.0.1
查找 git log
在整个工程中查找
在使用git log查看像linux内核、ffmpeg这样代码量巨大,修改提交频繁的修改历史记录时,我们免不了要使用过滤机制快速查看我们关心的某个 部分的修改记录,执行:
git log --grep='ffplay'
可以查看log中所有包含ffplay字段的修改,但是有时只使用一个过滤条件还是过滤不掉大量无用信息,比如我们今天想查看ffmpeg中ffplay中音视频同步机制的相关修改记录,这时必须添加两个过滤条件才能有效过滤无用信息。这时需要执行:
git log --grep='ffplay' --grep='sync' --all-match
加上--all-match就可以同时使能两个过滤条件。
-p选项
要查看每次具体修改的内容,加上-p选项即可。
在某个文件中精确查找
当我们想追踪某个文件某个地方的改动是哪个版本加入的时候,我们就需要追踪这个文件的所有历史记录。
通过git log --follow -p xxx浏览xxx文件所有的修改记录后,可以进行如下search操作:
- 
    /<term>:/后加上你想查找的关键字,和vim下输入?效果一样,然后可以通过n和N进行上一处关键字和下一处关键字位置的跳转。
- 
    :<line>: 这个和vim的功能一样,就是输入:加你想跳转到的行号。不过因为本身git log输出浏览时并没有行号信息,所以需要搭配grep工具使用。
回退linux内核到某个tag
今天需要在Linux内核某个版本上编译perf工具,回退到某个tag的操作流程如下:
- 执行git tag 查看所有的tag,并找到需要的tag,比如我需要回退到v4.4版本
- 执行git show v4.4 查看对应的commit id
- 执行git reset –hard xxxx 这里的xxxx就是上面的commit id
- 执行git log 查看我们当前版本是否是我们需要的版本
从Github上clone仓库到本地
哎,这么简单的一个命令,格式经常忘记,直接记下实例操作算了.
git clone git@github.com:saiyn/xxx.git
追溯ffmpeg最新版本修复内存泄露的版本
最近几天一直在解决项目中使用ffmpeg进行mjpeg硬件加速编码出现内存泄露的问题,通过我司内部的内存泄露检测工具初步定位到是 ffmpeg代码的问题,试着在当前ffmpeg版本3.2.2进行修复,发现没有效果,然后决定升级到3.3.3版本试一下。果然,mjpeg的硬件加速编码的内存泄露问题在新版本上已经解决了。
想通过git追溯是在哪个版本上进行怎样的修改的,我在自己笔记本上执行git pull想先更新到github上的最新版本,但是提示plese commit your changes or stash them的错误,已经忘记之前在已经ffmpeg源码时加入了什么修改代码,所以没有执行git stash先保存起来我之前的修改,而是直接执行git reset --hard进行版本回退,再执行更新。
然后执行git log --grep="memory leak",筛选一些版本修改记录,发现一个历史提交好像有关联:

查看某个文件某个历史版本的内容
1.首先使用命令git log --follow -p xxx 查看该文件各个历史版本,类似于svn上的show log菜单。
2.再使用命令git show yyy:xxx,其中yyy为上面命令可以获得的commit版本编号。
远程仓库控制问题
今天在我的新笔记本上clone我的github上的日志仓库时,碰到一个问题。 执行完’git clone git@github.com:saiyn/homepage’后发现homepage文件夹里面只有一个.git和一个LISENSE 我想起来我的仓库中确实只有gh-pages分支是有代码的,于是我执行命令查看分支情况:
$git branch
* master
  gh-pages
于是我认为只要执行一下切换分支命令’git checkout gh-pages’应该就可以了。但是发现执行完前面这个命令后,homepage目录里依然只有2个文件。 网上搜了一下发觉,原来是我没有理解远程仓库的概念。
$git branch -r
 origin/HEAD -> origin/master
 origin/gh-pages
 origin/master
$git checkout origin/gh-pages
执行完上面的命令就可以将远程仓库中的相应分支代码给download下来了。也就是说’git checkout’命令用于本地和远程仓库效果是不一样的。要注意远程仓库的概念。