以下所有用法以ubuntu为例
0.git是什么?
1. 安装 git
1.1 安装git客户端
sudo apt-get install git
1.2.配置用户和邮箱
$git config --global user.name "Your Name"
$git config --global user.email "email@example.com"
每个机器都必须带name和email,作为提交者的唯一凭证;
git config命令的--global参数,表示这台机器上的所有Git仓库都会使用这个地址
git config --list //查看当前配置
1.3 配置默认编辑器为vim
ubuntu上默认时nano, 我还是习惯用vi;
git config --global core.editor vim
2. 本地仓库基本用法
2.1 创建一个本地repo
$mkdir project;cd project
$git init //初始化一个本地空仓库
2.2 提交一个commit
(1) 添加文件
$git add readme.txt
git add:把一个文件添加到git 系统中,或者说添加到git缓存中;
git rm:把版本库的文件或目录删除
git mv:移动或重命名文件;
提交包括新建,或者修改的文件(直接编辑);
(2)git status命令
查看仓库当前的状态
git status //查看哪些文件被修改
git status:
跟踪三类命令
traced,已跟踪的文件,已经在版本库里;
ignored,被忽略的文件,通常临时文件;
untracked,未跟踪的文件,通常新建文件属于这一类;
(3)查看本地文件修改内容
git diff
查看两个指定版本的内容差异:
git log
git diff vxxx1 vxxx2
(4)add修改到暂存区
git add . //添加当前目录及其子目录下所有改动;
git add .../xxx //可以add指定文件
(5)提交修改
add所有改动到暂存区后,提交到本地仓库;
$git commit -m "wrote a readme file"
git commit -s //社区规范,自动添加Signed-off-by:
2.3 修改最近一次提交
可以将修改文件,或者注释,提交到最近一个commit(commit-ID保持不变);
git diff
git add .
git commit --amend
重新修改最近一次提交,如果文件内容为改变,那么只改变log信息
2.4 如何修改最近一个提交的作者
git commit --amend --author="leon <leon@qq.com>"
2.5 查看历史版本log记录
git log
git log --pretty=oneline //log简短信息
git log --oneline
git log --author=Linus --oneline //按行查看某人的所有提交
git log --patch-with-stat //查看当前patch提交差异,包括文件名和内容
git show xxx_id //查看指定commit_id的提交差异
其他用法:
git log xxxx
xxx可以是一下:
绝对提交名:40位16进制哈希值
符号引用:HEAD 指向最近的提交
相对提交名字:
master表示master分支头,
master^表示master分支倒数第二个commit
范围:
符号..表示一个范围,master~12..master~10:表示master分支上倒数第11和10个提交;
git log --pretty=short master~5..master~3
git log --pretty=short master~5..master~3 --stat
查看分支合并情况
git log --graph --pretty=oneline --abbrev-commit
6.回退到上一个版本
git reset --hard HEAD^
上上个:HEAD^^
上N个:HEAD~n
恢复到指定版本
git reset --soft xxxx //将HEAD引用指向给定的提交,索引和工作内容不变, 只回退commit,本地修改保持;如还要再提交,直接commit即可;
git reset --mixed xxxx :索引内容跟着改变,工作目录内容不变;
git reset --hard xxxx //索引和工作内容都改变,放弃所有修改,回退到XXX版本
git reflog:列举历史回退记录,可以查询版本ID号
回退到远程remote同步
git reset --hard origin/master
7.查看工作区和版本库区别
git diff显示在缓存中或未在缓存中的改动
git diff HEAD -- readme.txt
git diff:显示尚未缓存的改动:
git diff --cached:查看已经缓存的改动
git diff HEAD 查看所有的改动
git diff --stat 显示摘要
8.撤销修改
1)撤销工作区修改
git checkout -- readme.txt
2)撤销暂存区修改
git reset HEAD readme.txt //撤销指定文件readme.txt的add
git reset HEAD //撤销所有add
3)若没提交到远程版本库,撤销本次提交
git reset //版本回退
9.删除文件
1)删除
git rm test.txt
git commit -m "remove test.txt"
2)误删:恢复最新版本
git checkout -- test.txt // "--"不能省,否则变成了切换到另一个分支
3)从版本库里删掉某文件的版本管理,但是不删除本地文件
git rm -r --cached -n xx.txt //-n只是打印,不真正执行
git rm -r --cached xx.txt//执行rm命令,本地文件会保留
10.建立一个服务器仓库
server端:
mkdir git_test.git
sudo chmod 777 -R git_test.git/
git_test.git/
git --bare init //初始化一个服务端的空仓库
client端:
git init
git add cpu.txt
git status
git commit -s
git log
ifconfig
git remote add origin ssh://leon@192.168.0.128:/opt/git_test.git
git remote remove origin //删除远程分支
git remote -v
git push origin master //当前分支master推送到远程仓库origin,同名分支
cd ..
git clone ssh://192.168.0.122:/opt/git_test.git git_test2
cd git_test2/
11.分支操作
1).查看分支
git branch
git branch -a
git show-branch -a //查看详细分支,和提交信息
2)创建分支
git branch <name>
git branch xx/dev创建分层的分支
3)切换分支
git checkout <name>
4)创建+切换分支
git checkout -b <name>
5)删除分支
git branch -D <name>
6)合并某分支到当前分支
git merge <name> //Fast-forward模式合并,就是直接把master指向dev当前提交
git merge xxx //两个分支按提交时间顺序合并
git rebase xxx //站在另一个分支的肩膀上
按时间abcdefg
a-b-c-e
\d-f-g
qgit --all
图形化查看git commit
用途:
当需要合并别人修改,考虑用merge
当你的开发工作或者提交的补丁需要基于某个分支之上,用rebase命令,比如向内核社区提交补丁;
用--no-ff 强制禁用Fast forward模式
开发中,一般master分支用来发布版本,而开发工作在各自的dev分支开发并提交,只有稳定版本才合并到master
git merge --no-ff -m "merge with no-ff" dev
这样普通模式合并后,就有历史分支信息,能看出来曾经做过合并;
12 解决冲突
1) merge方式
git merge dev
git merge debug
Auto-merging dev.c
CONFLICT (content): Merge conflict in dev.c
Automatic merge failed; fix conflicts and then commit the result.
leon@leon:~/lab03_merge$ vim
vim dev.c //手动修改
git status
git add .
git merge --continue //继续merge
2)rebase方式
git rebase dev
$ git rebase debug
First, rewinding head to replay your work on top of it...
Applying: malloc 100bytes
Using index info to reconstruct a base tree...
M dev.c
Falling back to patching base and 3-way merge...
Auto-merging dev.c
CONFLICT (content): Merge conflict in dev.c
error: Failed to merge in the changes.
Patch failed at 0001 malloc 100bytes
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
leon@leon:~/lab03_rebase$
git am --show-current-patch
vim dev.c //手动修改
git add dev.c
git rebase --continue //继续rebase
git log
3)patch方式
git format-patch -1
生成0001-dev-malloc-100-bytes.patch
git checkout master
git am 0001-dev-malloc-100-bytes.patch
查看patch
vim .git/rebase-apply/0001
git apply .git/rebase-apply/0001 --reject //生成改动文件
//手动修改
vim dev.c dev.c.rej
git add dev.c
继续patch
git am --resolved
git log
13. git revert把某个提交给撤销
git revert master~3
a-b-c-d-e-f-g master
-->
a-b-c-d-e-f-g-d' master
14.git cherry-pick 摘草莓
从某个git tree或分支上摘取一个commit到当前分支
把dev的f节点commit摘到master分支上
a-b-c-d-e-f-g-h dev
\v-w-x-y-z master
git checkout master
git cherry-pick dev~2
a-b-c-d-e-f-g-h dev
\v-w-x-y-z-f' master
15管理远程仓库
git remote命令
git remote -v //查看远程仓库地址
git remote add name_xxx 添加远程仓库地址
git remote show xxx //查看远程仓库的所有信息
git remote update //抓取远程版本库中所有可用更新到本地仓库里面
git fetch xxx //抓取远程xx版本库到本地
添加和删除远程分支
添加:
git push 远程主机名 本地分支名:远程分支名
git push orgin master
git push origin master:dev //若dev不存在,就新建一个远程dev分支
删除:
git push 远程主机名 :远程分支名
git push 远程主机名 -d 远程分支名
拉取远程指定分支:
git pull 远程仓库门 远程分支名
git pull linux linux-5.13
Git push 命令用于从将本地的分支版本上传到远程并合并。
命令格式如下:
git push <远程主机名> <本地分支名>:<远程分支名>
//如果本地分支名与远程分支名相同,则可以省略冒号:
git push <远程主机名> <本地分支名>
实例
以下命令将本地的 master 分支推送到 origin 主机的 master 分支。
$ git push origin master
相等于:
$ git push origin master:master
如果本地版本与远程版本有差异,但又要强制推送可以使用 --force 参数:
git push --force origin master
推送标签到远程仓库
默认情况下,git push并不会把tag标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。
1.push单个tag,命令格式为:
git push origin [tagname]
$ git push origin tag_20170908 //将本地 tag_20170908的tag推送到远端服务器
2.push所有tag,命令格式为:
git push [origin] --tags
git push --tags
或
git push origin --tags
git如何将本地分支同远程分支进行关联
将本地分支同远程分支进行关联,可以分为以下2种情形:
情形1:
本地已经创建了分支dev(以dev为例,下同),而远程没有
可以通过以下2种方法在远程创建分支dev,并与本地分支进行关联:
方法1: git push -u origin dev
方法2: git push --set-upstream origin dev
情形2:远程已经创建了分支dev,而本地没有
在本地创建分支并与远程分支进行关联,也有2种方法:
方法1分为两步:
step1:先将远程分支pull到本地 git pull origin dev
step2:再在本地创建分支并与之关联,又有2种方法
(1)git checkout -b dev origin/dev
(2)git checkout -b dev --track origin/dev #可以简写为git checkout --track origin/dev
方法2:可以在pull远程分支的同时,创建本地分支并与之进行关联
git pull origin dev:dev-------两个dev分别表示远程分支名:本地分支名
12.github远程仓库
1)创建SSH Key
cd ~/.ssh
ssh-keygen -t rsa -C "youremail@example.com"
一路回车会生成id_rsa和id_rsa.pub两个文件
id_rsa是私钥, id_rsa.pub是公钥
登陆github.com,选择setting/ssh keys/
添加SSH key
把公钥id_ira.pub内容复制过去
2)gitHub上创建一个仓库,然后把本地仓库与之关联,进行同步
git remote add origin git@github.com:luteresa/testgit.git //关联一个远程库,远程库名字origin
git push -u origin master //推送master分支所有内容到远程origin仓库的master分支
3)从已经存在的远程仓库克隆
git clone git@github.com:luteresa/gitskills.git
... //本地代码管理操作
git push -u origin master //推送到远程仓库
//加上"-u"参数,Git不但把本地的master分支内容推送到远程的master分支,还会把它们关联起来,以后推送或者拉取时就可以简化命令;
git push origin master
13.过滤不需要提交到仓库的文件
在工作区目录下创建.gitignore文件,提交到仓库则生效
https://github.com/github/gitignore
GitHub做好了很多文件,可以稍加修改拿来用;
如果文件被.gitignore过滤掉,但又确实想添加,可以强制添加
git add -f file.txt
或者发现无法提交,可能是.gitignore写的有问题,可以查询哪个规则写错了
git check-ignore -v file.txt
17.BUG分支, “储藏”现场
每个Bug都可以通过临时分支来修复,修复后合并分支,然后删除临时分支;
比如接到临时bug任务issue-101, 先将工作现场临时“储藏”起来,修复后,再恢复现场
git stash
这是用git status查看工作区是干净的,因此可以放心创建临时分支
git checkout -b issue-101
在issue-101上修复bug,提交;
git add;
git commit -m "fix bug 101"
修复完成后,切换到master分支,完成合并,删除issue-101分支
git checkout master
git merge --no-ff -m "merged bug fix 101" issue-101
git branch -d issue-101
完成后,切换到工作区继续干活
$ git checkout dev
Switched to branch 'dev'
$ git status
# On branch dev
nothing to commit (working directory clean)
工作区是干净的,恢复储藏代码
git stash list
两种方式恢复:
1)git stash apply; //恢复工作区内容
git stash drop; //删除stash内容
2)git pop //恢复的同时把stash内容删掉
git stash list 查看
可以多次stash,然后恢复制定stash
@git stash list
stash@{0}: WIP on dev: 6224937 add merge
git stash apply stash@{0}
18.Feature分支
添加定制新功能时,为不影响主干代码,可以建立featurea分支,完成后合并,最后删除feature分支
Feature分支操作与BUG分支类似,当在没有合并之前,if删除,就会丢失掉修改,如果要强行删除,
git branch -D featrue-branch
19.多人协作
1).查看远程库信息,使用
git remote -v;
2)本地新建的分支如果不推送到远程,对其他人就是不可见的;
3)从本地推送分支,使用
git push origin branch-name
如果推送失败,先用git pull抓取远程的新提交
4)在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
本地和远程分支的名称最好一致;
5)建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
6)从远程抓取分支,使用git pull,如果有冲突,要先处理冲突
20.标签管理
1)标签与分支类似,是指向commit的指针,但是标签不可移动;
2)TAG就是给个容易记的名字,与原来某个commit绑定一定;
3)默认创建标签给HEAD, 也可以指定一个commit
git tab v1.0
git log --pretty=oneline --abbrev-commit
git tab v0.9 ea7edc2
git show v0.9
4)可以指定标签信息
git tag -a v0.1 -m "version 0.1 released" 3628164
5)可以用PGP签名标签
git tag -s
签名采用PGP签名,因此,必须首先安装gpg(GnuPG),如果没有找到gpg,或者没有gpg密钥对
git show
用PGP签名的标签是不可伪造的,因为可以验证PGP签名。
6)修改标签,可以删除
git tag -d v0.1
7)推送标签到远程
git push origin v0.1
一次性推送所有未被推送到远程的标签
git push origin --tags
8)标签已推送远程,删除方法
git tag -d v0.1 //本地删除
git push origin :refs/tags/v0.1 //再push远程删除
21.使用GitHub
1)在GitHub上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送pull request给官方仓库来贡献代码;
1)
22.关联本地仓库与远程仓库
1)git remote add origin http://luteresa@192.168.13.168:10009/r/AF_SAMPLE.git
2)git pull origin master
3)git push -u origin master
23.本地仓库与多个远程仓库了关联
1)查询本地仓库的远程关联
~$ git remote -v
origin ssh://admin@192.168.13.168:29418/AF_SAMPLE.git (fetch)
origin ssh://admin@192.168.13.168:29418/AF_SAMPLE.git (push)
2)add关联新的远程仓库
git remote add s1_3m ssh://admin@192.168.13.168:29418/S1_3M_AF.git
$ git remote -v
origin ssh://admin@192.168.13.168:29418/AF_SAMPLE.git (fetch)
origin ssh://admin@192.168.13.168:29418/AF_SAMPLE.git (push)
s1_3m ssh://admin@192.168.13.168:29418/S1_3M_AF.git (fetch)
s1_3m ssh://admin@192.168.13.168:29418/S1_3M_AF.git (push)
3)推送远程仓库
git push [远程库名] [本地分支名] : [远程分支名]
git push s1_3m s1_3m
4)从指定远程仓库pull
git pull s1_3m s1_3m
24.查看哪些文件是在版本控制下;
git ls-files
25.git注释换行
git commit -m '
1.it is a test;
2.linefeed;
'
26.修改文件名
git mv oldname newname
27.查询哪些文件在版本控制下
git ls-files
28.fork之后的本地仓库与原仓库同步;
场景:
在github,从祖师爷torvalds的帐号里,fork了linux的源码;将自己github里的Linux仓库clone到本地供学习研究用;
自己的修改,也会及时提交到github仓库,问题来了,一段时间之后,torvalds的仓库有了很多更新,如何将这些更新同步到个人github仓库?
原仓库:https://github.com/torvalds/linux.git
个人仓库:https://github.com/luteresa/linux.git
step1:在本地仓库添加原仓库为上游代码库
$ git remote -v
origin https://github.com.cnpmjs.org/luteresa/linux.git (fetch)
origin https://github.com.cnpmjs.org/luteresa/linux.git (push)
$git remote add upstream https://github.com/torvalds/linux.git
$ git remote -v
origin https://github.com.cnpmjs.org/luteresa/linux.git (fetch)
origin https://github.com.cnpmjs.org/luteresa/linux.git (push)
upstream https://github.com/torvalds/linux.git (fetch)
upstream https://github.com/torvalds/linux.git (push)
由于众所周知的原因,给github加下速,添加upstream2;
leon@pc:~/work/myHub/kernel$ git remote -v
origin https://github.com.cnpmjs.org/luteresa/linux.git (fetch)
origin https://github.com.cnpmjs.org/luteresa/linux.git (push)
upstream https://github.com/torvalds/linux.git (fetch)
upstream https://github.com/torvalds/linux.git (push)
upstream2 https://github.com.cnpmjs.org/torvalds/linux.git (fetch)
upstream2 https://github.com.cnpmjs.org/torvalds/linux.git (push)
step2,同步上游原仓库修改到本地;
leon@pc:~/work/myHub/kernel$
git fetch upstream2
leon@pc:~/work/myHub/kernel$ git log
commit 8404c9fbc84b741f66cff7d4934a25dd2c344452
Merge: a79cdfb 36f0b35
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date: Wed May 5 13:50:15 2021 -0700
Merge branch 'akpm' (patches from Andrew)
Merge more updates from Andrew Morton:
"The remainder of the main mm/ queue.
143 patches.
可见,本地仓库实际代码尚未同步
查看本地分支:
leon@pc:~/work/myHub/kernel$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/upstream2/master
step3:合并上游原仓库修改到本地
$ git merge upstream2/master
leon@pc:~/work/myHub/kernel$ git log
commit a050a6d2b7e80ca52b2f4141eaf3420d201b72b3
Merge: 1434a31 f8b61bd
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date: Mon May 24 16:03:24 2021 -1000
可见本地源码已同步到最新
step4: 本地修改推送到github
git push
git push origin HEAD --force
29git 获取标签对应的版本
git clone 整个仓库后使用,以下命令就可以取得该 tag 对应的代码了
原仓库:
打标签
git tag tag_name xxxx
另外目录:
git clone kernel/ -b tag_name new_dir
但是,这时候 git 可能会提示你当前处于一个“detached HEAD" 状态。
因为 tag 相当于是一个快照,是不能更改它的代码的。
如果要在 tag 代码的基础上做修改,你需要一个分支:
cd new_dir
git checkout -b branch_name tag_name
这样会从 tag 创建一个分支,然后就和普通的 git 操作一样了。