- 创建新的远程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’命令用于本地和远程仓库效果是不一样的。要注意远程仓库的概念。