Git学习推荐网站:廖雪峰-Git教程 - 廖雪峰的官方网站,通俗易懂,简单粗暴,就是平俗的语言,好懂、粗暴的那种
git学习进阶~国外经典git学习网站:Git - Book
目录
1. 全局配置和单个项目仓库的用户名邮箱配置
如果你配置的全局的用户名和邮箱是公司的,而自己也有私人用户名和邮箱来开发自己项目,这样可能一台电脑需要设置多个git用户名配置的项目。如果你不进行配置用户名和邮箱的话, 则会使用全局的, 这个时候是错误的, 正确的做法是针对个人的项目, 在自己的项目根目录下进行单独配置
-
全局配置
-
目前大部分公司都已经使用gitlab或github管理项目代码, 在使用git时相信大家都配置了一个全局的用户名和邮箱
$ git config --global user.name "gitlab Name"
$ git config --global user.email "gitlab@xx.com"
$ git config --list
- 非公司或非个人的单个项目
如果你配置的全局的用户名和邮箱是公司的,而自己也有私人用户名和邮箱来开发自己项目,这样可能一台电脑需要设置多个git用户名配置的项目。如果你不进行配置用户名和邮箱的话, 则会使用全局的, 这个时候是错误的, 正确的做法是针对个人的项目, 在自己的项目根目录下进行单独配置
$ git config user.name "mygitlab Name"
$ git config user.email "mygitlab@xx.com"
$ git config --list
git config --list查看当前配置, 在当前项目下面查看的配置是全局配置+当前项目的配置, 使用的时候会优先使用当前项目的配置
参考原文:https://blog.csdn.net/hyupeng1006/article/details/116154080
- 删除单个项目的用户邮箱参数,恢复使用全局配置
由于每个git项目下都会有一个隐藏的.git文件夹 ,将终端的工作目录设置到,相应的项目根目录下,执行ls -all命令,显示所有文件,即可看到.git的隐藏文件夹。通过cd .git 进入该目录,发现该目录下有个config文件,采用open config 命令打开,删除个人参数即可:
[user]
name = XXX(自己的名称英文)
email = XXXX(邮箱)
保存,command+s 即可。
2. git diff命令
git diff
顾名思义就是查看difference,知道了对readme.txt
作了什么,这一步查看是在git add xx.file之前,再把它提交到仓库就放心多了
3. git add 和 git commit命令
commit而不是add在git中类似于保存,版本回退就是基于commit保存机制进行的,比如:git reset --hard HEAD(表示当前版本)/HEAD^(表示上一个版本)、--hard commit_id。
git add 文件夹 ~git添加整个文件夹及内容
git add -A 提交所有变化
git add -u 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new)
git add . 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
git add . 会把本地所有untrack的文件都加入暂存区,并且会根据.gitignore做过滤,但是git add * 会忽略.gitignore把任何文件都加入
4. 版本回退命令
- 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- file
。在git add file之前 - 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令
git reset HEAD <file>
,就回到了场景1,第二步按场景1操作。在git add之后,在git commit之前 - 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,git reset --hard HEAD^,不过前提是没有推送到远程库。在git commit之后,在git push之前
- git reflog记录你的git命令,用来寻找回退以前的版本
-->从暂存区恢复工作区,git resotre --worktree readme.txt
-->从master恢复暂存区,git restore --staged readme.txt
-->从master同时恢复工作区和暂存区,git restore --source=HEAD --staged --worktree readme.txt
5. 文件删除rm
$ rm test.txt
rm也算一种修改,提交使用git rm而不是git add
$ git rm test.txt
$ git commit -m "remove test.txt"
git checkout -- test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!
6. 创建密钥 SSH key
第1步:在主目录下生成SSH key。
ssh-keygen -t rsa -C "youremail@example.com"
第2步:查看生成的密钥 key
cd ~/.ssh
ls
在.ssh目录里有id_rsa和id_rsa.pub两个文件,id_rsa是私钥,不能泄漏出去;id_rsa.pub是公钥,可以被公开添加到github中。
cat id_rsa.pub # 查看公钥
第3步:将公钥id_rsa.pub添加到github中
github -》account settings -》SSH Keys -》add SSH Key
6.1 生成个人访问令牌
Error:如果遇到remote: Support for password authentication was removed on August 13, 2021. Please use a perso
reference:【突发】解决remote: Support for password authentication was removed on August 13, 2021. Please use a perso-CSDN博客这是因该从2021.8.13开始,github不再支持用户名密码验证方式了
需要创建个人访问令牌 (personal access token).
第1步:生成个人访问令牌
github -》setttings -》developer settings -》personal access tokens -》generate new tokens
Note: 生成个人access tokens时要勾选☑️权限,要不然project无法访问知识库!
第2步:将access令牌添加到项目中
# 修改现有项目的url
git remote set-url origin https://<your_token>@github.com/<USERNAME>/<REPO>.git
<your_token> 访问令牌;<USERNAME> github用户名;<REPO> 知识库名称
6. 添加远程库
-
首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库:
- 关联本地版本库与远程版本库。
git remote add origin git@github.com:xxx/xxx.git
- 推送上去。把本地库的内容推送到远程
git push -u origin master
-->我们第一次推送master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
--> 强制推送:git push --force 或 git push -f origin master
7. 删除远程库
此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。
如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name>
命令。使用前,建议先用git remote -v
查看远程库信息:
$ git remote -v
origin git@github.com:michaelliao/learn-git.git (fetch)
origin git@github.com:michaelliao/learn-git.git (push)
然后,根据名字删除,比如删除origin
:
$ git remote rm origin
8. 两种创建版本库方式
- 先创建本地版本库再推送远程版本库,git init --> git push
- 先创建远程版本库再克隆到本地文件夹,git clone
9. 更新本地版本库
git分布式系统的目的就是合作,如果其他人的进度比你快,并且提交了好几次commit to remote repository,现在remote repository的版本领先你本地的版本库了,肿么办?-->更新本地库
- 先用git fetch到remote repository中获取远程仓库状态和数据更新,获取你本地仓库还没有的数据
- 然后git merge与本地仓库合并。虽然一般都是合并master,但也可以指定合并分支 <远程repo> <本地repo>:<本地分支>
另一种方法是git pull=git fetch + git merge,它比较简单粗暴,直接硬合并,你无法看到通过git fetch得到的状态更新数据。
--> 怎么git push origin master不好使,git push才行? --未解答
-->git fetch和git pull区别:
Git fetch和git pull区别为:远端跟踪分支不同、拉取不同、commitID不同。
一、远端跟踪分支不同
1、Git fetch:Git fetch能够直接更改远端跟踪分支。
2、git pull:git pull无法直接对远程跟踪分支操作,我们必须先切回本地分支然后创建一个新的commit提交。
二、拉取不同
1、Git fetch:Git fetch会将数据拉取到本地仓库 - 它并不会自动合并或修改当前的工作。
2、git pull:git pull是从远程获取最新版本并merge到本地,会自动合并或修改当前的工作。
三、commitID不同
1、Git fetch:使用Git fetch更新代码,本地的库中master的commitID不变,还是等于1。
2、git pull:使用git pull更新代码,本地的库中master的commitID发生改变,变成了2。
--> 最麻烦的问题:你本地执行了修改操作并commit,远程仓库也被其他人执行了好几次commit操作,造成无法合并的路径、版本冲突了,即both modified same-file,你不能git push、pull或者git merge最新的远程版本库
Your branch and 'origin/main' have diverged,
and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
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.md
解决方法:
- 一种方法是手动修改Git合并失败的文件为我们希望的内容,再提交
- 还有一种方法是抛弃本库对冲突文件的修改,全部替换为remote repository文件的内容。
git reset --hard FETCH_HEAD
10. git忽略文件
- 全局范围内有效的忽略文件
就是"版本库根目录/.git/info/exclude",全局范围内的所有忽略规则都以行为单位写在这个文件中;
- 局部范围内有效的忽略文件
就是.gitignore,这个忽略文件只对某一级目录下的文件的忽略有效;
如果某一个目录下有需要被忽略的文件,那么就可以在该目录下手工地创建忽略文件.gitignore,并在这个忽略文件中写上忽略规则,以行为单位,一条规则占据一行;
忽略配置语法:
以斜杠“/”开头表示目录;
以星号“*”通配多个字符;
以问号“?”通配单个字符
以方括号“[]”包含单个字符的匹配列表;
以叹号“!”表示不忽略(跟踪)匹配到的文件或目录;
忽略示例:
(1)规则:fd1/*
说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;
(2)规则:/fd1/*
说明:忽略根目录下的 /fd1/ 目录的全部内容;
(3)规则:
/*
!.gitignore
!/fw/bin/
!/fw/sf/
说明:忽略全部内容,但是不忽略 .gitignore 文件、根目录下的 /fw/bin/ 和 /fw/sf/ 目录;
(4).idea //忽略.idea文件夹及文件夹下文件
*.iml //忽略以.iml结尾的文件
参考:Baby小猪,https://www.jianshu.com/p/62a412b7a6e8;git设置忽略文件和目录 - wangmo - 博客园
11. 修改和合并多条commit信息
背景:Git项目,对同一个功能不断改进、多次远程提交生成commit记录的情况,不利于观看。
目的:为了保证一个功能点只有一条提交记录利于后续维护,需要利用git rebase命令对属于同一功能点的多条commit记录进行合并。
rebase:需要准备理解rebase的含义!!rebase的含义其实包括选基(rebase commit_id)和合并(pick,squash,fixup commit)两步,虽然选基和合并都遵循“前一步原则”,但rebase的commit_id和pick的commit_id绝对不一样!!
rebase的commit_id是要选择几个commits并入的那个commit_id的前一个commit_id;而几条commit_id要并入的那个commit_id是在vim里面的前一条id,用pick标记。即rebase选择的commit_id是所有操作commit_id的基,并不参与任何操作或者并入,比如说commit1、2、3、4,我打算将commit1、2并入commit3,那rebase选择的commit_id是4,commit1、2、3都在vim里面操作!
具体案例步骤参考:
————————————————
版权声明:本文为CSDN博主「书忆江南」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33588730/article/details/110230039
(1) 确定此次合并基于的base记录
既然要合并“Support”那一条与它上面三条的总共四次commit记录,就要以“Support”那条第一次提交记录的再下面那条“Merge branch”记录,作为本次合并的base记录。这点容易理解,就像造房子需要在地基之上建,第一次提交记录的再之前一次记录就是本次“地基”。因此输入以下命令开始此次记录合并,commit id就是选取的base记录的id:
git rebase -i 4560d5dd728c627291201eb8c04041628de7d5e4
(2) 合并多个commit id
使用git rebase -i命令后,会进入Git内置的vim界面,如下图所示:
vim操作: i--输入模式;esc--证明模式;shift+: +wq--保存退出
commit_id操作命令:reword-编辑commit信息;squash-将commit并入前一个commit中,并保留commit信息;fixup-将commit并入前一个commit中,不保留commit信息等。
--> 单纯地只编辑上一条写错的commit message不合并多个commit信息,可以用:git commit --amend
这四次提交涉及的代码改动都是需要的,但是只需要一条提交记录,因此先按“i”键进入INSERT模式,将后三次commit id前面的“pick”字样改为“s”(我个人用的是f),只有第一次的commit id前面是“pick”,然后按ESC键退出编辑模式,并输入:wq进行保存。注意如果是在Intellij IDEA的Terminal框里编辑rebase信息,那么在按ESC之后光标会回到代码区,此时输入的“:wq”会写到代码里,所以这种情况下按ESC键之后,要重新用鼠标点一下Terminal框里的区域,重新把光标定位回Terminal框中。
(3) 去除多余的commit描述
在上一个pick与squash编辑界面用:wq保存后,会跳出最后的commit描述编辑界面,如下图所示
这里按“i”键进入INSERT模式后,可以把不需要的后三条commit描述用“#”号注释掉,只留下第一次提交时那条蓝色高亮的“Support”描述,然后用ESC键退出编辑模式,再输入:wq进行保存。
(4) 完成rebase
在vim里面的commit操作结束之后,还要继续完成rebase操作,git有三个rebase继续命令:continue、skip、abort
git rebase --continue #表示合并顺利,可以继续完成rebase
git rebase --skip #表示rebase过程遇到冲突,是否要跳过不能合并的冲突
git rebase --abort #表示rebase合并出错,我要放弃这次rebase操作
rebase过程遇到冲突很常见,尤其是本地不同commit版本提交过程产生的冲突,我个人强烈不建议用skip跳过。
--> vi xx.file打开冲突文件,手工修改冲突,然后git add xx.file(表示冲突文件已经手工修改完毕),这时绝不要git commit!!最后,执行git rebase --continue完成rebase操作
在rebase过程中,最好每一步用git status观察rebase状态,输入合适的命令
(5) 远程强制提交
强制提交原因:因为合并多个commit后,本地版本库因为少了几个commits,会与远程库产生different commits冲突,git会建议你用git pull解决本地库与远程库different commits冲突,绝不!!
绝不能辛辛苦苦二十年,一朝回到解放前,你git pull了之后,本地库又会被远程库同化为原来的多个commit信息。所以必须在rebase完成后,强制push。
在命令行输入以下命令即可:git push -f origin 分支名 或 git push --force,将远程库的commit记录强制同化为本地库的commit记录。
如果本地分支与远程分支关联过,那么其中“origin 分支名”部分可以省略,强制提交后可以看到GitLab上关于该功能点只有一条commit记录了。
12. 分支管理
Git分支:Git把每次提交(commit)串成一条时间线,这条时间线就是一个分支。
- 主分支-master分支:master分支的master指针,用master指针指过的提交(commit)串成一条时间线。
- 指针-HEAD,指向当前分支指针,默认是master分支的master指针。
e.g. 一开始的时候,git用master指针指向最新的提交,再用HEAD指针指向master指针,这样就能确定当前分支,以及当前分支的提交点。
(1)创建分支
创建分支是在当前提交上新建一个分支指针dev,再把HEAD指针指向dev指针,这就表示当前分支在dev上。
git checkout -b dev # 创建并切换到dev分支
=git branch dev # 创建分支
git checkout dev # 切换到分支dev
或者用switch创建并切换到dev分支
git switch -c dev
(2) 查看分支
git branch
*表示当前分支
(3)切换分支
git checkout master
或
git switch master
(4)合并分支
git checkout master
git merge dev
解决git分支冲突:
git status,告诉我们冲突的文件,然后查看冲突文件,Git用
<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,删除以前的冲突内容。git commit -m "conflict fixed",先提交
再执行合并merge。
(5) 删除分支
git branck -d dev
13. git删除commit的历史大文件
problem:如果commit了大文件到本地git repository(即.git文件),则remote github会拒绝整体超过100M的repository推送。因为超过100M是要收费的!!
因为大型文件被commit进本地repository了,所以单纯删除commit提交记录一点用也没有,因为大型文件还是存在的!
solution:先checkout大型文件,然后通过git rm删除,将repository整理数据量减下来之后,再push到github。
第一步:找出本地repository中排名前10的较大文件
git rev-list --all | xargs -rL1 git ls-tree -r --long | sort -uk3 | sort -rnk4 | head -10
比如说:你找出了较大文件
100644 blob 6eb183ae3d234391eb8d0992bf2f69bd53e97153 2382860 data/lda_data/lda2vec_data/topics.pyldavis.npz
第二步:删除本地commit记录
git filter-branch --force --index-filter "git rm -r --cached --ignore-unmatch 'path-to-your-remove-file'" --prune-empty --tag-name-filter cat -- --all
第三步:主动更新本地git repository缓存和历史记录。因为commit记录删除了之后,较大文件还是会在历史记录中存在一段时间,不会马上消失,所以不主动更新的话,git repository整体文件大小不会下降。
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now
第四步:强制push到github上的repository
git push -f origin master #其中master为你要推送的分支