赞
踩
更新时间:
2024.6.20:重新复习了一下Git,并整理了Git命令到另一个博客
廖雪峰的官方网站-Git:https://www.liaoxuefeng.com/wiki/896043488029600
https://git-scm.com/downloads
找到安装包并完成安装。$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
$ git config --list
git config
命令的--global
参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
email可以不是真的。
1.为什么Git比其他版本控制系统设计得更优秀?因为Git跟踪并管理的是修改,而非文件。
2.Git在有些情形下不区分大小写,在有些情形下区分大小写,所以尽可能严格按大小写来
3.如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。
git init
命令可以初始化一个Git版本库。git add <file>
命令可以将文件提交到暂存区。git commit -m "message"
命令可以将文件从暂存区提交到版本库。可以多次使用
git add <file>
命令添加多个文件
可以使用git add .
命令添加目录下的所有文件
git commit
命令的-m
参数后面输入的是本次提交的说明。
git init
是一种初始化版本库的方法,还有一种方法是git clone
,可以将github
上别人开源的代码克隆到本地并进行版本管理。
$ git clone https://github.com/jquery/jquery.git
git status
命令可以查询工作区状态:文件是否修改,是否进入暂存区。git diff
命令可以查看修改内容。
git diff
是查看diffference,显示的格式是Unix通用的diff格式。
HEAD
指向当前版本,HEAD^
指向上个版本,HEAD^^
指向上上个版本,HEAD~100
指向往上数100个版本。git reset --hard HEAD^
可以回到上个版本git reset --hard commit_id
在版本间穿梭git log
命令查看提交历史,以便确定要回退的版本。git reflog
查看命令历史,以便确定未来版本的版本号。
git log
命令显示从最近到最远的提交日志
形如commit 9fa66a...
的是commit id
(版本号)
可以在git log
命令后面加上--pretty=oneline
参数,这样输出的内容会比较简略
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD的指向改变,并把工作区的文件更新
版本号没必要写全,一般只需要写前5-7位即可
git add
命令就是将文件提交到暂存区。master
分支。HEAD
指针。git add
添加到暂存区,则不会加入到commit
中git restore [--source=<>] [--staged] [--worktree] <pathspec>
命令(参考git restore文档)--staged
‘和”--worktree
“,则将’HEAD
’的内容恢复到工作区和暂存区--staged
”,则将’HEAD
’的内容恢复到暂存区--worktree
“,则将暂存区(’index
‘)的内容恢复到工作区--staged
‘和”--worktree
“,则默认将暂存区(’index
‘)的内容恢复到工作区
如果恢复源是暂存区,但暂存区没有内容,其实表示暂存区和HEAD是一致的,则从HEAD恢复内容,如果恢复源是暂存区,但是暂存区没有内容,会报错pathspec 'readme.txt' did not match any file(s) known to git
# 几个例子
git restore --staged readme.txt # 会将HEAD的内容恢复到暂存区
git restore readme.txt # 会将暂存区的内容恢复到工作区
git restore --source HEAD --staged readme.txt # 会将HEAD的内容恢复到暂存区
git restore --source 17539a readme.txt # 会将”17539a“标识的版本的内容恢复到工作区
git restore --staged --worktree readme.txt # 会将HEAD的内容恢复到暂存区和工作区
几个场景:
git restore readme.txt
# 方法一:先将HEAD恢复到暂存区,再将暂存区恢复到工作区
git restore --staged readme.txt
git retore readme.txt
# 方法二:同时将HEAD恢复到暂存区和工作区
git restore --staged --worktree readme.txt
# 直接版本回退
git reset --hard HEAD^
git rm test.txt
"命令:可以删除工作区的test.txt
文件,同时将此次删除操作提交到暂存区,然后只需要commit
,则版本库中test.txt
文件也删除了。git rm test.txt
git commit -m "remove test.txt"
test.txt
文件,则可以使用”git restore
“命令撤销删除。git restore --staged test.txt # 从版本库恢复test.txt文件到暂存区
git restore test.txt
注意这里不能直接使用"git restore test.txt"恢复test.txt文件,因为暂存区已经没有test.txt文件了
从来没有被添加到版本库就被删除的文件,是无法恢复的
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。
一般是找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
GitHub就可以提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。
ssh-keygen -t rsa -C "youremail@example.com"
后面的
your_email@youremail.com
改为你在 Github 上注册的邮箱,之后会要求确认路径和输入密码,使用默认的一路回车即可。
这样就会在家目录~/下生成.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,前者是私钥(不能泄露),后者是公钥
Github
,打开account=>settings
,左边选择SSH and GPG keys
,点击New SSH key
按钮,title随便填,在文本框内粘贴id_rsa.pub
文件中的内容。点击“Add Key
”。为什么Github需要SSH Key,因为因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。
GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。
learngit
仓库下运行命令:$ git remote -v # 查看远程库的信息
$ git remote rm origin # 删除关联的origin远程库
$ git remote add origin https://github.com/xxxx/xxxx.git
添加后,远程库的名字就是origin,这是Git默认的叫法,可以改成别的,但一般不建议。
$ git push -u origin master
用git push命令,实际上是把当前分支master推送到远程。
加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令(以后只需要git pull
就可以拉取)。
$ git push origin master
git remote -v
可以查看远程库信息$ git remote rm origin
这里的“删除”是指解除了本地和远程的绑定关系,并不是物理上删除了远程库。要真正删除远程库,需要登陆GIthub,在后台页面选择删除。
现在考虑先创建远程库,再从远程库克隆的情形。
gitskills
的仓库,并勾选Initialize this repository with a README
。git clone
命令克隆本地库$ git clone git@github.com:Nkehougaosuni/gitskills.git
GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
dev
分支,并切换到dev
分支$ git switch -c dev
# 参数`-c`表示创建并切换,相当于下面两条命令
$ git branch dev
$ git switch dev
git branch
命令查看当前分支$ git branch
* dev
master
git branch
命令会列出所有分支,当前分支前会标一个*
号
git merge dev
命令将dev
分支的工作成果合并到当前分支(master
分支)上$ git merge dev # 将dev分支合并到当前分支(master分支)上
Updating 150ffb8..2e9a1a2
Fast-forward
k.txt | 0
readme.txt | 3 ++-
2 files changed, 2 insertions(+), 1 deletion(-)
delete mode 100644 k.txt
git merge
命令用于合并指定分支到当前分支
Fast-forward
信息表示这次合并是“快进模式”,即直接把master指向dev的当前提交。
事实上还有别的合并方式
git branch -d dev
命令删除dev
分支$ git branch -d dev
Deleted branch dev (was 2e9a1a2).
不能删除当前所处的分支
Git鼓励使用分支完成某个任务,合并后再删掉分支。
在一个分支有工作尚未add或者commit,此时切换到其他分支,会出现问题。详情可以参考https://blog.csdn.net/w522301629/article/details/81331273
合并分支可能会存在冲突。假如在新建的feature1
分支上对readme.txt文件进行修改并提交。并切换到master
分支上对readme.txt文件进行修改并提交
这种情况下,git无法执行
快速合并
,只能试图把各自的修改合并起来,但这种合并可能有冲突。
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
使用
git status
可以告诉我们冲突的文件,然后必须手动解决冲突之后再提交。
Git用<<<<<<<,=======,>>>>>>>
标记出不同分支的内容
解决冲突并提交后的结果如下图。
使用git log --graph --pretty=oneline --abbrev-commit
也可以看到分支的合并情况。
最后删除feature1分支
合并分支的时候,git会尽可能使用fast forward
模式,这种模式下,删除分支后,会丢掉分支信息。
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出曾做过合并,而fast forward
合并则看不出来曾做过合并。
$ git merge --no-ff -m "merge with no-ff" dev # 在master分支下对dev分支进行普通合并
因为普通合并会创建一个新的commit,所以要加上-m参数,将commit的描述写进去。
此时通过git log --graph --pretty=oneline --abbrev-commit
命令就可以查看分支历史
$ git log --graph --pretty=oneline --abbrev-commit
master
分支应该是非常稳定的,仅用来发布新版本,平时不能在上面干活。
dev
分支是不稳定的。每个人都应该有自己的分支,并时不时往dev
分支上合并。
当在dev
分支上工作,但工作还没有commit
时(工作只进行到一半,无法提交),此时在master
分支上忽然有一个必须要修复的bug。这时候,可以使用git stash
命令将工作现场保存起来。
$ git stash -u
git stash -u
可以将包括工作区新增的文件也保存起来。详细可以参考:https://blog.csdn.net/lamp_yang_3533/article/details/80370380
对于切换分支开发,一般使用stash命令,不太建议用commit,如果用commit,会导致很多无效的提交,到时候追溯会比较麻烦
然后就可以放心在需要修改bug的分支上(如master
分支)创建临时分支(如issue-101
)来修改bug
$ git switch master
$ git switch -c issue-101
修改完bug后,提交,并切换到master分支完成对issue-101分支的合并。
# 修改readme.txt文件
$ git add readme.txt
$ git commit -m "fix bug 101“
[issue-101 e05ecd5] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)
$ git switch master
$ git merge --no-ff -m "mergerd bug fix 101" issue-101
$ git branch -d issue-101 # 删除issue-101
记住修改bug提交的commit-id号,后面复制这次提交需要用到。
然后重新回到dev分支,使用git stash pop
命令或者git stash apply
命令恢复工作现场。
$ git switch dev
$ git stash pop
cherry-pick
命令复制提交到当前分支dev分支是早期从master分支上分出来的,所以这个bug其实在dev分支上也存在。
可以使用cherry-pick命令修复同样的bug
$ git branch
$ git cherry-pick e05ecd5 # 复制一个特定的提交到当前分支
cherry pick命令可以让我们能复制一个或多个特定的提交到当前分支
使用git cherry-pick
前要保证工作区和暂存区是干净的,所以建议先使用stash命令,再使用git cherry-pick
命令。
关于git cherry-pick
的用法可以参考详解 git cherry-pick用法
feature
分支,在上面开发,完成后,再合并,最后删除该分支。git branch -D <分支名>
来强行删除master
分支和远程的master
分支对应起来,并且,远程仓库的默认名称是origin
。git remote -v
命令可以查看远程库信息。$ git remote -v
origin https://github.com/Nkehougaosuni/learngit.git (fetch)
origin https://github.com/Nkehougaosuni/learngit.git (push)
显示了可以抓取和推送的origin地址,如果没有推送权限,就看不到push地址
git push origin master
命令将本地的master分支推送到远程库。$ git push origin master # 推送master分支到远程库
$ git push origin dev # 推送dev分支到远程库
并非所有本地分支都一定要往远程推送
master分支是主分支,要时刻与远程同步
dev分支是开发分支,团队所有成员都需要在上面工作,所以需要和远程同步
bug分支只用于本地修改bug,没必要推到远程
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发
$ git clone ...
此时只能看到master分支,但是是可以通过
switch
命令切换过去到其他分支的,具体有哪些分支存在可以通过branch -r
命令查看
git switch dev
切换到dev
分支$ git switch dev
Switched to a new branch 'dev'
branch 'dev' set up to track 'origin/dev'.
这个命令会自动将dev分支关联(跟踪到)到远程库的dev分支
git pull origin <远程分支名>
能将远程的分支合并到当前分支$ git pull origin dev
如果当前分支和远程分支已经建立起了跟踪链接,则可以简写为git pull
git pull
试图合并git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。git pull
,而pull的时候又产生了冲突。这是因为pull实际上是git fetch+git merge,而merge如果产生冲突,会在一个分叉上生成一个冲突合并的提交,然后需要手动解决冲突并在当前分支产生一个提交。
git pull -r
则实际上是git fetch+git rebase
:git先将master指针指向拉取分支,然后根据当前分支有几个提交,就生成rebase的几个阶段。每个阶段中如果有冲突,都需要解决冲突并提交,然后再使用git rebase --continue命令进入下一个阶段。
rebase
命令可以把本地分叉的提交历史整理成直线关于
git merge
和git rebase
的区别可以参考:https://blog.csdn.net/michaelshare/article/details/79108233
git tag -a 标签名 -m "说明文字" commit_id
可以在当前分支打标签,commit_id
不填,则默认打在最新提交的commit
上-a指定标签名,可写可不写
git tag
查看所有已经打上的标签标签是按照字母顺序排列的
git show <标签名>
可以查看标签信息。标签总是和某个commit挂钩,如果某个commit即出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
标签是指向commit的死指针,分支是指向commit的活指针
git tag -d 标签名
可以删除本地标签创建的标签都只存储在本地,不会自动推送到远程
git push origin <标签名>
可以将某个本地标签推送到远程git push origin --tages
可以一次性推送全部尚未推送到远程的本地标签git push origin :refs/tags/标签名
可以删除远程的标签略
.gitignore
文件各种软件的gitignore文件可以参考:https://github.com/github/gitignore
git add -f 文件名
可以突破.gitignore
的限制强行提交.gitignore
文件中要排除指定文件的语法是:! 文件名
git config --global alias.st status
就可以用git st
代替git status
命令$ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
.git/config
文件中.gitconfig
中$ cat ~/.gitconfig
[filter "lfs"]
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
[user]
name = Nkehougaosuni
email = 124226697+Nkehougaosuni@users.noreply.github.com
[alias]
st = status
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
$ sudo apt-get install git
$ sudo adduser git
id_rsa.pub
文件,把所有公钥导入到/home/git/.ssh/authorized_keys
文件里,一行一个/srv/sample.git
,在/srv目录下输入命令:$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
$ sudo chown -R git:git sample.git
$ git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
$ git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。
$ git clone git@server:/srv/sample.git
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。