Skip to main content
 首页 » 编程设计

Git Authoritative Guide 学习

2022年07月19日56mayingbao

 一、git命令

1.git add
  -u : 将工作区中所有改动的文件添加到暂存区(修改、删除),但是不提交未被git跟踪的文件
  -i : 可以进入交互界面选择性提交
  -A : 相对于-u,它还提交新建的文件

2.git format-patch -1 从获取最新一次提交的patch

   git format-patch -1 commit-id 获取某一次提交的patch,eg:$ git format-patch -1 0d7c516

3.git grep :在工作区目录下查找,更高效

4.git commit --amend 如果git commit时提交信息写错了可以使用它来修改,修改的是最新一次提交的
  eg:git commit --amend -m "use gitg to commit but qgit to change=="
  使用图形化窗口gitg或qgit修改更方便!gitg功能更强大!
  git rebase -i <hash> :如果修改的不是上一次提交,还要变基(目前还不知怎么用)

5.git rm --cached new.txt 如果不小心把多余的文件添加到暂存区,如此时还没有commit,使用此删除记录(文件还在)
  git reset -- filename : 会把暂存区中的文件置为非staged的状态,为git add的反操作,同上。

6.git rev-parse --git-dir 查看自己的git仓库在哪
  git rev-parse --show-toplevel 显示工作区根目录
  git rev-parse --show-prefix 显示当前目录与工作区的相对路径

      $ cat .git/config  可以得出 URL 远程版本库网址

      $ git ls-files :查看此版本库管理哪些文件

7.git commit --allow-empty -m "this is empty commit" 没有任何修改也可提交--空白提交

8.git log -s :simple
git log --oneline :只显示一行commit信息

9.git commit -sm "xxxx" : -s表示这次提交的信息中会自动包含提交的签名和邮箱地址

10.git clean
  -fd : 会清除工作区中未在暂存区中的文件和文件夹
  -nd : 查看会删除那些文件,夹。

11.git cat-file
  -t 哈希值 :显示此哈希值代表什么对象,commit(提交),bolb(文件),tree(目录)
  -p 哈希值 :打印此哈希值表示的对象的内容

12.HEAD表示当前分支最新提交,^表示上一次提交

13.git reflog show master 筛选显示master分支上的信息
  git reflog后使用 git status <hash>查看更改

14.使用git reset --hard <hash> 后此hansh的提交会填充暂存区和工作区,之前的修改会丢失
  但是git reflog记录了所有提交信息,使用git reset --hard <old_hash>还会回到之前的状态

15.git merge 对git check out迁出的无名分支merge到分支之上

16.git checkout -- file : 会以暂存区的文件覆盖工作区的文件
  git checkout -- . 和 git checkout . 会丢弃掉工作区相对于暂存区的所有更改。
  只会对工作区中没有受到git管理的文件操作。

  git checkout <hash> <文件名>  此迁出此hash值时的此文件,例如$ git checkout 084e8df Makefile  常用的Makefile可以专门提交到一个分支中,使用时这样checkout出来,很方便。

17.git ls-files --with-tree=HEAD^ 查看历史版本库中的文件列表

18.git tag查看里程碑,也即是查看发布软件的版本号,
  git describe 描述距这个发布版本目前多了几次修改,最近的提交的hash值

19..gitignore忽略文件:作用域为此目录及其根目录,只对git管理的文件进行忽略,在其中添加要被忽略的文件

20.git archive -o last.zip HEAD   或者 last.tar.gz 归档打包操作,如果直接使用tar -cf xxxx会将此目录下的所有文件打包过去,无论是不是要忽略的文件

21.查看一个命令的路径:which xxx

22.git blame third.c 追溯一个文件的提交

23.git diff : 工作区与暂存区
  git diff --cached 暂存区与版本库
  git diff HEAD 工作区与版本库
  git diff A :比较工作区和里程碑A
  git diff --cached A 比较暂存区和里程碑A
  git diff B A :比较里程碑B和里程碑A

24.git log --stat -2 : 比直接-2多出了更改信息

git log --stat 可以查看每次提交修改的文件。

25.git checkout HEAD -- third.c 从版本库中取出third.c到暂存区和工作区

26.将两次提交合并为一次提交:
  git reset --soft HEAD^^
  git commit -m "xxxxxxx"

27.git show-ref 显示各应用哈希值

28.git clone git@gitlab.com:xxxx/bmp.git manage :clone下拉后重命名为manage

29. git status 用于对比工作区、暂存区、版本库之间的区别

30.
  # git fsck 查看版本库中(包含暂存区和工作区)的未被任何应用关联的松散对象
  dangling blob 02a2010152982a96e1962cb98eb6d459cd8089af
  dangling:就是没有被任何应用直接或间接关联的对象
  若已经commit就会被记录在reflog中,使用git fsck --no-reflogs查看,然后将.git/logs下面
  清空(此时git log正常显示,git reflog为空),就可以通过git prune清理了
  # git prune 清理未被关联的对象,释放空间

31.git reflog expire --all 让90天前的reflog过期
  git reflog expire --expire=now --all

32.git rerere gc对合并冲突的历史记录进行过期操作

33.git管家
  git gc --prune=now :立即删除非关联的对象,--prune=now会传送个git reflog expire --expire=now,否则2周后清理
  git gc: 会对关联的对象进行增量存储,会对非关联的对象变为松散存储

34.git init --bare创建的没有工作区(直接就是.git下的内容)的版本库也可以使用git log等命令

35.git pull : 先拉下来,然后再与本地提交进行合并,合并的先后顺序应该是由提交顺序决定的。

36.git ls-files -s 合并冲突时来看,第三个字段只有在冲突时才会大于0,会看到冲突文件的三个副本
  git show :1:README 显示双方冲突的祖先版本
  git show :2:README 显示当前冲突文件在当前分支中修改的副本
  git show :3:README 显示当前冲突文件在合并分支中修改的副本
  也可以使用git mergetool 但是没感觉它好用

37.merge冲突解决
1.修改了相同文件的相同地方产生git merge冲突,先手动编辑冲突文件的冲突区域并去掉冲突标识符,再git add,再commit
就是合并提交。

2.合并的分支都对同一文件重命了不同的名字产生git merge冲突,删除掉一个冲突文件,再提交即可实现merge 提交

3.git config merge.conflictstyle diff3 、merge(默认)更改默认的文件内容冲突标识,注意没有等号!

4.git merge 有冲突的文件会存在暂存区中,有时代码升级需要提交有冲突的merge后的代码,然后各个模块拉下来修复冲突,此时可以直接add暂存区的代码,然后进行commit.

38.git打补丁

1.已经提交
获取补丁:git format-patch -1
打补丁: git apply 0001-2.patch
也可以迁出操作,获取历史提交的补丁

2.未提交
git diff master > 000-patch
将master分支上相对于当前提交的所有提交打成一个名为000-patch的patch

回退一次提交打完这次提交的补丁后还能merge
打patch后再修改文件后patch就打不成功了(应该是index变了),文件内容改回去后又可以了!
git diff 2test.c后就可以直接切换分支了,而不用commit!再checkout回去,git diff --cached发现暂存区已经被覆盖了

3.使用commit-id打补丁
git diff acb8cd15() 4ff35d80() > 0000-patch
生成了一个000-patch,使用 git apply进行打补丁。

git diff old_hash new_hash > diff.patch 查看两次提交之间的变化,注意后面的是最新的提交。

使用 git format-patch -1 new_hash old_hash 不行

使用# git format-patch -1 AudioPolicyManager.cpp 来取出某一个补丁中只与某个文件有关的补丁。 

39.git rm --cached file_path_name 删除暂存区中的文件(git add时多添加了可以使用)

40.只恢复一个文件: $ git checkout -- filename
这条命令把hello.rb从HEAD中签出并且把它恢复成未修改时的样子.

41.git revert 是撤销某次操作,此次操作之前和之后的commit都会被保留,并且会把这次撤销作为一次最新的提交;
git revert HEAD 撤销前一次 commit
git revert HEAD^ 撤销前前一次 commit
git revert commit-id 撤销指定的版本,撤销也会作为一次提交进行保存。git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,
版本会递增,不影响之前提交的内容。
git reset 是撤销某次提交,但是此次之后的修改都会被退回到暂存区;
git reset是还原到指定的版本上,这将扔掉指定版本之后的版本

42.交互式变基
git rebase -i ommit_id进行交互式变基,修改交互时的message信息即可实现修改ID、修改提交顺序的目的(rebase到自己分支之前的状态)

①交互式变基后在repo sync代码后可能会出现:
error: source/linux/: prior sync failed; rebase still in progress
解决:
git rebase --abort
git am --abort(可能不需要)

②git merge来合并所看到的commit的顺序是按时间的先后顺序的,git rebase来合并所看到的commit的顺序不是。
③git pull --rebase,这里表示把你的本地当前分支里的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后
把本地当前分支更新为最新的"origin"分支,最后把保存的这些补丁应用到本地当前分支上。

43.检出某个分支中的某个文件

[ubuntu @linux]$git checkout topic/rvc drivers/media/i2c/scxx.c 加的是文件的路径名
[ubuntu @i2c]$ git checkout topic/rvc_v3.4 sc00.c

45.只查看某个人的提交记录:[ubuntu @linux]$ git log --author="Jinda Fu"

git log --committer=xxxx 也是只看某个人的提交

46. git cherry-pick --continue cherry-pick解决冲突后继续cherry-pick

   git cherry-pick --abort 取消cherry-pick操作。

注:git cherry-pick后diff看到的改动不是实际的改动,git add到暂存区后git diff --cached看到的才是本次cp的带来的改动。

47. git add directory -A 将这个目录中的说有修改全部提交,包括删除的和新增的

48.查看两个tag之间的提交

$ git log --pretty=oneline tag1...tag2 --pretty=oneline打印出完整的hash
34ba8419b037f8fc018d554db641806c4abcdae6 Merge branch 'topic/sd-reader' into 'master'

$ git log --oneline tag1...tag2 --oneline只打印出部分hash
34ba841 Merge branch 'topic/sd-reader' into 'master'

49. git设置别名
$ git config --global alias.br branch
$ git config --global alias.li "log --oneline"
--global的修改会体现在~/.gitconfig文件中(若不加--global是.git/config),也可以直接修改这个文件进行git配置。

50. 要查看远程库的信息,用git remote, -v显示更详细的信息

51.查看git版本库位置

    strace -e 'trace=file' git status      // 追踪git status的磁盘访问
 git rev-parse --show-toplevel       // 显示工作区根目录
 git rev-parse --git-dir                    // 显示版本库.git目录所在位置
    git rev-parse --show-prefix          // 相对于工作区根目录的相对目录
   git rev-parse --show-cdup            // 从当前目录后退到工作区的深度
在git工作区的某个子目录下执行操作时,会在工作区目录中依次向上递归查找.git目录,找到的.git目录就是工作区对应的版本库,.git所在目录就是工作区的根目录,文件.git/index记录了工作区文件
的状态(实际上是暂存区的状态)。

52. 查看某个提交修改了哪些文件  

git log -3 --stat  查看最近三次提交每次修改的文件

git log hash_id --stat -1  查看某一次提交修改的文件

53. 给 git commit 信息加一个模板

# cat ~/.git_log_message 
This is test,log is:  
 
# git config --global commit.template  ~/.git_log_message //将这个模板配置到git中 
 
# git commit    //提交后就可以在这个模板上修改log信息了

# git log --pretty='%an %cn 以看到author和committer

54. 查看某个提交在哪个分支上

git branch -r --contains <commit_id>

55. git只克隆repo仓库中的某一个版本库

$ cat ./repo/projects/android/kernel/configs.git/config
[remote "origin"]
url = ssh://xxxxxxxxxx/kernel/configs
review = http://gerrit.xxxxxxx

$ git clone ssh://xxxxxxxxxx/kernel/configs

repo只拉取一个仓库:

repo init -u ssh://gerrit.xxxx -b <breach name> -m <xml文件> //只拉取.repo仓库

repo sync -c <仓库名> //fetch下来git仓库,xml文件中project name=<仓库名>

56.删除分支 

删除服务器远端的分支:

git push origin –delete 分支名

如果是要删除本地已经合并了的分支:

git branch –d 分支名

删除本地未合并的分支:

git branch –D 分支名

57.git stash #把所有没有提交的修改暂存到stash里面。可用git stash pop恢复.

58. git restore 旧的git版本中没有这个命令
git restore --staged [file] : 表示从暂存区将文件的状态修改成 unstage 状态。
git restore --staged . 表示将当前目录所有暂存区文件恢复状态
$ git restore -s HEAD~1 READEME.md // 该命名表示将版本回退到当前快照的前一个版本
$ git restore -s 91410eb9 READEME.md // 改命令指定明确的 commit id ,回退到指定的快照中
$ git reset --soft HEAD^ // 该命令表示撤销 commit 至上一次 commit 的版本

二、使用git打补丁

1.检测补丁有无问题
$ git apply --check xxx.patch

2. error: xxxxx: patch does not apply
出现这种一般会是补丁冲突,这种一般是强制打上补丁(使用--reject)后根据产生的*.rej文件来手动解决冲突。

3. warning: xxxx.c has type 100644, expected 100755
出现这种警告一般是文件内没有冲突,但是文件的权限发生变动。一般没有影响。

4.强制打补丁
$ git apply --reject xxx.patch
然后再手动修改冲突,find ./ -name *.rej找到这些冲突的补丁,手动打上

5.git am同样有--reject选项,添加这个选项可以将能打上的补丁先打上,冲突的文件生成*.rej文件。

39.分支变基
1.可以checkout out很久以前的提交,然后git checkout -b sfl创建新分支,gitg会发下它很靠后,然后
git rebase master就发现它骑在了master分支的头上,然后commit一次发现在master头上有一次提交

40.本地分支分支重命名
git branch -m old_local_branch_name new_local_branch_name

41.远程分支操作:
1.$ git branch -a :查仓库的所有分支,包括远程分支。

2.$ git push origin --delete <branchName> : 删除远程分支
或者$ git push origin :<branchName> : 推送一个空分支到远程分支,其实就相当于删除远程分支

3.$ git push origin --delete tag <tagname> : 删除远程分支的tag

4.git tag -d <tagname> : 应该是删除本地tag
git push origin :refs/tags/<tagname> 推送一个空tag到远程tag,也就达到了删除远程分支的tag的效果

5.$ git remote show origin : 查看远程分支的状态

6.$ git remote prune origin : 若此分支对应的远程分支已经被删除,使用它来将本地对应分支从本地版本库中去除

7.重命名远程分支 :其实就是先删除远程分支,然后重命名本地分支,再重新提交一个远程分支。eg.将devel分支重命名为develop分支
git branch -av 查看分支
git push --delete origin devel 删除devel分支
git branch -m devel develop 重命名本地分支
git push origin develop 推送本地分支

8.$ git push --tags : 推送本地tags

9.$ git fetch origin tag <tagname> : 获取远程tag
参考:
https://makandracards.com/makandra/621-git-delete-a-branch-local-or-remote
https://blog.zengrong.net/post/1746.html

 42.合并服务器上的代码

创建一个本地master分支: git branch master, git checkout master
reset到远程服务器上的master分支:git reset --hard origin/master
将远程的update分支merge到master分支: git merge origin/topic/update --no-ff (--no-ff:创建合并提交)
将本地的master分支推送到远程服务器:git push origin master:master
查看验证:git fetch -p gitg &

将master分支merge到项目分支:
git merge master --no-ff
git push origin g8s/master:g8s/master

43.在历史提交中快速查找iperf相关提交
$ git log --oneline | grep iperf

44.增加签名: git commit -s -m "commit message"   -s签的是自己的名字

45.使用git am来保留patch作者的信息

patch -p1 < 0001--JFFS2-community-fix-with-not-use-OOB.patch
这样来打patch,但是这样会把这些有用的信息丢失。由于这些patch显然是用git format-patch来生成的,所以用git的工具应该就可以很好的做好。

git -am 可以保留这些信息。
在使用git -am之前,你要首先git am –abort 一次,来放弃掉以前的am信息,这样才可以进行一次全新的am。
不然会遇到这样的错误: .git/rebase-apply still exists but mbox given.

git-am 可以一次合并一个文件,或者一个目录下所有的patch,或者你的邮箱目录下的patch.

git am XXX/*.patch 将XXX目录下的所有patch打上去,这里git就会按照文件名的顺序一次am这些patch
git am *.patch

git am 和 git apply的区别: git am不需要再提交一次,而git apply打完补丁后需要从新提交一次。

在解决完冲突以后,可以用git add来让git知道你已经解决完冲突了。
可以运行git am –abort,撤销整个am的东西
如果忽略某一个patch,可以运行git am –skip来跳过这个patch.

46.$ git log --author=Li.ming  查看某一个人的提交,注意是.而不是,

$ git log origin/g6s/master --author=Xiao.liang

47. .git/config文件中有版本库的网址等信息

48. 将缓存的文件删除

$ git rm –cached "文件路径" 不删除物理文件,不修改物理文件的内容,仅将该文件从缓存中删除;

$ git rm –f "文件路径" 不仅将该文件从缓存中删除,还会将物理文件删除

49. 若是想提交删除一个文件的提交:

$ git rm -rf xxxx.c
$ git commit

50. 查看一个版本库在服务器上的位置和主分支
$ git rev-parse --git-dir //查看到.git版本库的位置
$ cat .git/config

...... 
[remote "origin"] 
url = ssh://gerrit.scq.abc.com:14562/platform/vendor/lk    //版本库在服务器上的位置: platform/vendor/lk 
projectname = platform/vendor/lk     
[branch "master/Q/SM8210"]    //服务器上的分支,就是拉下来时的分支。若是断头的,就没有分支信息 
remote = origin 
merge = refs/heads/master/Q/SM8210

 51.git常用alias配置

sun@ubuntu:~/$ cat ~/.gitconfig  
[user] 
        name = xxx 
        email = xxx@xxx.com 
[alias] 
        st = status 
        ci = commit 
        st = status     
        co = checkout 
        ci = commit 
        br = branch 
        lo = log --oneline 
        la = log --author 
        lg = log --graph 
        dir = rev-parse --git-dir 
[commit] 
[core] 
        editor = vim 
[color] 
        ui = auto 
[push] 
        default = matching

52. .git/config文件

$ cat .git/config  
... 
[remote "origin"] 
        projectname = kernel/msm-4.19 //git仓库的名字 
...

git使用小技巧:

1.git log:
    git log --oneline ./ 只看当前目录下的所有文件的提交记录
    git log --oneline app_test.c 只看与app_test.c相关的提交
    git log --oneline --graph ./ 对当前目录下的文件的提交以graphic的形式看


二、本地git配置
1.使git带颜色显示
git config --global color.ui true
2.git命令自动补全
需要在/etc/profile和~/.bashrc中添加
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
但是最好不要添加,会导致Ubuntu无法登陆,将其单独写成一个脚本使用时执行一次。
由此导致无法登陆解决方法:
ctrl + alt + F1进入命令终端,然后删除更改。
3.禁止非快进试推送
git [--git-dir=/path/to/xxx.git] config receive.denyNonFastForwards true


3.三级配置
git config -e :修改此git仓库配置.git/config,显示如下
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@gitlab.com:TYTHT/bmp.git
[branch "master"]
remote = origin
merge = refs/heads/master

git config -e --global :修改针对此用户的git仓库配置~/gitconfig,显示如下
[color]
ui = true
[user]
name = pinctl
email = 2634520619@qq.com

git config -e --system :修改针对此系统的git仓库配置的/etc/gitconfig,里面暂时为空

 三、在github上创建版本库

GitHub 是一个网站,它提供 Git 仓库托管服务的。 只要注册一个 GitHub 账号,就可以免费获得 Git 远程仓库。
对于第 1 次使用 GitHub,需要:
(1) 创建 SSH Key:$ ssh-keygen -t rsa -C "your email"
(2) 注册 GitHub 用户:登录 https://github.com/ 注册账户
(3) 在 GitHub 里添加 SSH Key:点击网页右上角的按钮,选择“Settings”, 将第一步生成的~/.ssh/id_rsa.pub内容添加到Key栏后点击“Add Key”
(4) 创建仓库:点击网页右上角的“+”号,选择“New repository”:

GitHub 需要SSH Key的原因是要识别出你推送的提交确实是你推送的,而不是别人冒充的,而 Git 支持 SSH 协议,所以, GitHub 只要知道了你的公钥,就可以确认
只有你自己才能推送。

GitHub 允许你添加多个 Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的 Key 都添加到 GitHub,就可以在每台电脑上往 GitHub 推送了。

在 GitHub 上免费托管的 Git 仓库,任何人都可以看到喔(但只有你自己才能改)。

(5) 添加文件并推送到版本库
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/xxxx/Android_work.git
git push -u origin master

(6)下载和查看源码
a.可以直接在版本库的网址上查看源码
b.下载:git clone https://github.com/xxxx/Android_work.git

四、总结

1.每次git commit,工作区必须是干净的(即所有修改都已经git add; 是工作区,不是暂存区)
2.分支名如果不像这样topic/msater,而是一个简单的名字的话,就算是有分支,好像还是在master分支之上。
3.gitg是从最新更改开始画图,git log是从HEAD开始打印,gitg显示的select branch就是没有分支名的迁出分支
4.git checkout和git reset不同,前者是迁出,HEAD指向并没有变,后者HEAD变了。
5.mv针对工作区的修改 git mv是针对暂存区的修改
6.暂存区变了就可以使用git commit, 而没有必要非要先git add等操作
7.gitg也可以完成commit功能!
8.修改相同文件的不同地方merge时不会产生冲突,相同地方会产生冲突。

五、问题

1. 使用Yocto 编译新BSP的时候可以把build/tmp目录下的所有文件删除,若还是不行,可以把下面两个目录下的*.done文件全部删除,然后重新编译即可。
build/downloads/
build/downloads/git2

六、优秀资源链接

1.廖雪峰git教程

https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001374385852170d9c7adf13c30429b9660d0eb689dd43a000

七、git图形化显示

1.支持图形显示的话可以使用gitg/qgit工具。

2.不支持图形显示的话,可以使用git  log --graph显示。

八、补充

1. git cp -n 中途停下来,修改后再提交,提交后Change-Id不变,可以规避一些基于Change-Id的检查。

2. 查看2个hash之间的提交

$ git lo -5 
hash_1 
hash_2 
hash_3 
hash_4 
hash_5 
 
$ git lo <hash_5>..<hash_1> 
hash_1 
hash_2 
hash_3 
hash_4

类似于前开后闭,hash长的短的都行。

3. 查看两次git提交之间的差异

$ git lo -3 
hash_1 
hash_2 
hash_3 
 
$ git diff <hash_3> <hash_1> --stat 
hash_1 
hash_2

显示的是这两次提交的改动状态,也类似于前开后闭。


本文参考链接:https://www.cnblogs.com/hellokitty2/p/8152056.html