Git GitHub笔记

Jan 25, 2016


记录开发中实际涉及的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).

git_0


打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下输入?效果一样,然后可以通过nN进行上一处关键字和下一处关键字位置的跳转。

  • :<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",筛选一些版本修改记录,发现一个历史提交好像有关联:

mem



查看某个文件某个历史版本的内容

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