Git笔记
安装git:
apt install git
创建版本库:
git init
添加文件到版本库:
git add 文件
提交文件到仓库:
git commit -m “注释”
查看仓库当前的状态信息:
git status
查看修改内容和之前版本的区别,在git add之前可以看到
git diff 文件
查看提交的历史记录
git log 加上 --pretty=oneline 一行输出
版本回退:往前回退多个版本用HEAD^^ 100的话使用HEAD~100
git reset --hard HEAD^
回到指定版本:
git reset --hard 版本号的前几位
查询之前执行的命令:历史命令,帮助回到之前的版本
git reflog
git add 文件到暂存区 git commit 提交到工作区,commit的是已经在暂存区的内容,将暂存区里的所有内容提交
**场景1:**当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
。
**场景2:**当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>
,就回到了场景1,第二步按场景1操作。
git当删除工作区的文件text.txt后,第一个场景,删除版本库中的该文件,git rm test.txt 然后 git commit -m "remove test.txt " ;第二个场景,恢复工作区的文件从版本库,执行 git checkout – test.txt
创建新的ssh密钥添加到github:
以下是重新生成 SSH 密钥并将其添加到 GitHub 帐户的步骤:
1. 打开终端并输入以下命令:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
2. 按 Enter 键三次,接受默认文件名和位置。
3. 输入以下命令将新生成的 SSH 密钥添加到 ssh-agent:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
4. 复制新生成的 SSH 公钥。您可以使用以下命令将其复制到剪贴板:
pbcopy < ~/.ssh/id_rsa.pub
5. 转到您的 GitHub 帐户设置页面,选择“SSH 和 GPG 密钥”,然后单击“新 SSH 密钥”按钮。
6. 在“标题”字段中输入一个描述性标题,然后将剪贴板中的 SSH 公钥粘贴到“密钥”字段中。
7. 单击“添加 SSH 密钥”按钮。
现在,您应该能够使用新生成的 SSH 密钥访问您的 GitHub 存储库。
添加远程仓库:
$ git remote add origin git@github.com:github账户名/仓库名.git origin:远程库的名字
推送本地库的内容到远程库:
git push -u origin master #第一次推送master所有的内容,加上-u,保证本地和远程的分支关联起来
$ git push origin master #之后提交
删除远程库:
git remote rm origin
删除远程库之前建议使用git remote -v
查看远程库信息:
$ git remote -v
origin git@github.com:github账户名/learn-git.git (fetch)
origin git@github.com:github账户名/learn-git.git (push)
克隆远程仓库:
git clone git@github.com:github账户名/仓库名.git
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
解决冲突:
准备新的feature1
分支,继续我们的新分支开发:
$ git switch -c feature1
Switched to a new branch 'feature1'
修改readme.txt
最后一行,改为:
Creating a new branch is quick AND simple.
在feature1
分支上提交:
$ git add readme.txt
$ git commit -m "AND simple"
[feature1 14096d0] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)
切换到master
分支:
$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Git还会自动提示我们当前master
分支比远程的master
分支要超前1个提交。
在master
分支上把readme.txt
文件的最后一行改为:
Creating a new branch is quick & simple.
提交:
$ git add readme.txt
$ git commit -m "& simple"
[master 5dc6824] & simple
1 file changed, 1 insertion(+), 1 deletion(-)
现在,master
分支和feature1
分支各自都分别有新的提交,变成了这样:
HEAD
│
│
▼
master
│
│
▼
┌───┐
┌─▶│ │
┌───┐ ┌───┐ ┌───┐ │ └───┘
│ │───▶│ │───▶│ │──┤
└───┘ └───┘ └───┘ │ ┌───┐
└─▶│ │
└───┘
▲
│
│
feature1
这种情况下,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告诉我们,readme.txt
文件存在冲突,必须手动解决冲突后再提交。git status
也可以告诉我们冲突的文件:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
我们可以直接查看readme.txt的内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,我们修改如下后保存:
Creating a new branch is quick and simple.
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed
现在,master
分支和feature1
分支变成了下图所示:
HEAD
│
│
▼
master
│
│
▼
┌───┐ ┌───┐
┌─▶│ │───▶│ │
┌───┐ ┌───┐ ┌───┐ │ └───┘ └───┘
│ │───▶│ │───▶│ │──┤ ▲
└───┘ └───┘ └───┘ │ ┌───┐ │
└─▶│ │──────┘
└───┘
▲
│
│
feature1
用带参数的git log
也可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit #查看分支合并图
* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/
* b17d20e branch test
* d46f35e (origin/master) remove test.txt
* b84166e add test.txt
* 519219b git tracks changes
* e43a48b understand how stage works
* 1094adb append GPL
* e475afc add distributed
* eaadf4e wrote a readme file
最后,删除feature1
分支:
$ git branch -d feature1
Deleted branch feature1 (was 14096d0).
合并分支时,Git会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息
首先,仍然创建并切换dev
分支:
$ git switch -c dev
Switched to a new branch 'dev'
修改readme.txt文件,并提交一个新的commit:
$ git add readme.txt
$ git commit -m "add merge"
[dev f52c633] add merge
1 file changed, 1 insertion(+)
现在,我们切换回master
:
$ git switch master
Switched to branch 'master'
准备合并dev
分支,请注意--no-ff
参数,表示禁用Fast forward
:
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
因为本次合并要创建一个新的commit,所以加上-m
参数,把commit描述写进去。
合并后,我们用git log
看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* e1e9c68 (HEAD -> master) merge with no-ff
|\
| * f52c633 (dev) add merge
|/
* cf810e4 conflict fixed
...
可以看到,不使用Fast forward
模式,merge后就像这样:
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash
一下,然后去修复bug,修复后,再git stash pop
,回到工作现场;
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>
命令,把bug提交的修改“复制”到当前分支,避免重复劳动,但是需要git stash
命令保存现场,再git cherry-pick ,最后再 git stash pop,此时可能会有冲突,需要处理冲突;
开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>
强行删除。
多人协作:
-
查看远程库信息,使用
git remote -v
; -
本地新建的分支如果不推送到远程,对其他人就是不可见的;
-
从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交; -
在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致; -
建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
; -
从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
rebase
- rebase操作可以把本地未push的分叉提交历史整理成直线;git rebase
- rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
tag
-
命令
git tag <tagname>
用于新建一个标签,默认为HEAD
,也可以指定一个commit id; -
命令
git tag -a <tagname> -m "blablabla..."
可以指定标签信息; -
命令
git tag
可以查看所有标签。 -
git show <tagname
> 查看标签详细信息 -
命令
git push origin <tagname>
可以推送一个本地标签; -
命令
git push origin --tags
可以推送全部未推送过的本地标签; -
命令
git tag -d <tagname>
可以删除一个本地标签; -
命令
git push origin :refs/tags/<tagname>
可以删除一个远程标签。