Git 命令集合
一、创建、提交、修改,查看
创建本地仓库
使用 git init
后,会创建一个 .git
隐藏文件夹,这个文件夹是我们的版本库
mkdir newFolder
cd newFolder
git init
查看路径:
pwd
添加,提交
添加单个文件:
git add <file/folder>
git commit -m "add a new file"
添加更新的文件:
git add -u
也可以用 commit -am
来仅添加已经跟踪的更新的文件:
git commit -am "msg" # -a可以让更新的文件添加到库中(新建的未跟踪的文件,不会添加到库中)
添加未跟踪的文件:
git add $(git ls-files -o --exclude-standard)
添加所有文件:
git add .
添加所有未跟踪、修改的文件,并且会根据 .gitignore
过滤 ; git add *
不会根据 .gitignore
过滤(过滤文件不会直接添加进入,但是会有提醒)
git add .
git add *
添加多个文件:
git add f1.txt f2.txt
git commit -m "add two files."
查看当前状态,是否被修改:
git status
对比文件,查看修改的地方:
- 查看所有文件的改动。如果改动部分尚未提交到暂存区(尚未 git add .),则默认是用版本库的的版本和当前工作区对比。如果已经使用
git add .
命令,则会用暂存区和当前工作区对比,此时如果想要用暂存区和版本库对比,可以加上--cached
git diff [--cached]
- 查看某个文件的改动
git diff xx.txt
- 查看版本之间的改动
git diff commitID1 commitID2 <file> # file可以省略,则对比两个版本之间的所有不同,加上file,则只对比某个文件的不同之处
- 仅查看所有改动的文件名(不显示内容变动)
git diff --name-only <commitID1> <commitID2>
显示文件
现有如下状态的文件改动:
$ git st
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage) # 暂存区中 git add,重命名,删除的文件
modified: a
renamed: b -> bb
deleted: d
Changes not staged for commit: # 工作区,已修改未add的文件
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: c
Untracked files:
(use "git add <file>..." to include in what will be committed)
t/
- 从工作区提取所有的修改,重命名的文件。(不管有没有add进暂存区,都会查出来,已经删除的文件不会显示)
$ git ls-files -c
a
bb
c
- 提取没有git add 的文件
$ git ls-files -m
c
- 提取所有未跟踪的文件
$ git ls-files -o --exclude-standard
t/p/b
二、版本回退
查看提交的历史记录:
git log [-number] # 后面可以接数字:git log -2,查看最近的两次记录。不加 -数字,会显示所有的记录。
回到上一个版本
HEAD表示当前版本,HEAD^ 表示上一个版本,HEAD^^ 表示上上个版本,HEAD~100 表示上100个版本。
git reset --hard HEAD^
reset有三种模式,reset --hard, reset --soft, reset,假设我们当前是版本5,想要回到版本3,它们三个的区别是:
reset --hard 版本3: 会将工作区、暂存区、版本库的内容全部回退到版本3,此时工作区、暂存区清空了。
reset --soft: 会将两个版本之间差异的部分放到暂存区,此时直接git commit,就可以直接回到版本5
reset : 会将两个版本的差异放到工作区。此时如果想要回到版本5,需要git add,然后git commit
查看历史记录
通过git log查看历史记录,使用 commit 号回退:只需要写前几位就行了
git log
git reset --hard 1094a
git reset --hard 10941 <file_name> # 可以单独回退某个文件
通过reset命令回退到某一版本后,无法查看之前的最新的版本了(未来的版本),可以使用这个查看:
git reflog
工作区和暂存区
你的git仓库正常的文件夹,就是你的工作区。在git仓库中,当你 git init
后,会自动生成一个.git
的隐藏文件夹,它是 git 的版本库,库里面有一个叫 stage
的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫 HEAD
, 第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
撤销修改的方法
1.撤销工作区的修改,尚未使用add
方法。即只在工作区修改,但是尚未提交到暂存区的修改。(如果你使用了add 提交到了暂存区,它只能让你回到暂存区的状态;没有使用add方法,可以让你回到版本库的状态,也就是撤销所有工作区的修改)
git checkout -- xx.txt # 仅撤销某个文件的更改
git checkout . # 撤销所有的更改
2.撤销暂存区的修改,并放回到工作区:使用了add
方法,提交到了暂存区,但是没有使用commit
方法提交到当前分支。
git reset HEAD <file> # 先撤销暂存区的修改,放回到工作区
git checkout -- xx.txt # 再撤销工作区
删除文件
git rm xx.txt # 从版本库中删除已经跟踪的文件
git rm --cached xx.txt # 从版本库删除某个跟踪的文件,但是本地不删除它(仅仅取消跟踪)
git clean -fd # 批量删除所有未跟踪的文件
rm xx.txt # 删除某个未跟踪的文件
还原删除的文件
git checkout -- test.txt # -- 代表不指定版本,也就是从head指针恢复,如果指定 commitId,则可以从某个版本恢复文件
三、分支管理
创建分支并切换
第一种
git checkout -b dev
第二种(个人试了没用,可能和git版本有关)
git switch -c dev
git checkout
加上 -b
代表创建分支,并切换到当前分支,等同于下面的命令:
git branch dev # 创建分支
git checkout dev # 切换分支
git switch dev # 另一种切换分支的方法
查看分支
git branch
合并分支:
将 dev 分支,合并到当前分支上
git merge dev
通常,合并分支时,如果可能,Git会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward
模式,Git就会在merge时生成一个新的 commit,这样,从分支历史上就可以看出分支信息。
git merge --no-ff -m "merge with no-ff" dev
删除分支
git branch -d dev # 如果没有合并分支,可能删除不掉
git branch -D dev # 强制删除
合并冲突
当两个分支有冲突时,无法自动完成合并,可以手动查看文件,用 vi 命令打开文件并修改冲突部分,然后正常的使用 git add
和 git commit
完成合并。
git使用 <<<<<<<, ======, >>>>>>> 来标记不同分支的内容。
$ cat a.txt
I love my mlllllllla
<<<<<<< HEAD # HEAD 是当前分支的名称
=======
aaaaaaaaaaaaaaaaaaa
>>>>>>> f1 # f1 是合并进来的分支的名称
<<<<<<<
和=======
之间的数据,是当前分支的代码。
=======
和>>>>>>>
之间的数据,是别的分支上的代码。根据需要,修改代码,并删除
<<<<<<<, ======, >>>>>>>
这三个标识符,即可使用git add xx、 git commit -m "xx"
完成合并。
查看合并记录:
git log --graph
Bug 分支
假设你当前分支的工作做到一半,还不能提交,但是又需要回到工作区初始的状态来做些别的工作,那可以用 stash
将现场存起来。它可以保存你所做的所有更改,并且将工作区恢复到上次版本的状态(所有未提交的修改,全部清除掉)
- 保存现场
git stash [-k] [-u] # -k,-u,-a是可选项,-k代表保持索引(如果你修改了一个文件,并且已经 git add,那么使用这个参数,可以保持文件已经 git add 的状态,否则,会将工作区恢复到上次版本的状态); -u可以将 untracked 的文件,也保存起来(即从来没有出现在库里的新文件),-a可以保存所有文件,哪怕文件已经在.gitignore中被忽略
- 查看stash
$ git stash list
stash@{0}: On master: msg # 序号越小,越新。就像堆栈一样,
stash@{1}: WIP on master: 865ab8f9 update and debug cases
- 恢复最近的一次stash,并手动删除
git stash apply
git stash drop
- 恢复stash并自动删除
git stash pop [--index] # 如果之前使用了 -k 参数,使用 --index可以恢复git add 的状态。否则git add的文件,会回到工作区,变成未 git add 的状态。
- 恢复特定的stash,需要先用
git stash list
查看,然后 apply 恢复
git stash apply stash@{0}
- 给 stash 加备注
git stash push -m "msg" # 其实 git stash 和 git stash push 是一个意思,只不过想要使用 -m参数,就需要写全,也就是加上 push。
- 查看stash
git stash show [commitID] # 查看stash的变动
- 清空所有stash
git stash clear
同步分支
你用 master 创建了一个分支 bug0,在 bug0 上把 bug 修复了,然后把 bug0 和 master 合并了,这时 master 是修好的,但是 master 的另一个分支 dev 还没有修复好,那怎么能将 dev 上的 bug 也修好?
bug0分支提交修改时:会有一个commit id :5051635
/Desktop/github (bug0)
$ git commit -m 'bug fixed'
[bug0 5051635] bug fixed
Committer: Wang <zng@local>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:
git config --global user.name "Your Name"
git config --global user.email you@example.com
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 1 insertion(+)
然后切换到 dev 分支,使用 cherry-pick
命令让我们复制一个特定的提交到当前分支:
git cherry-pick <commit>
比如:
/Desktop/github (dev)
$ git cherry-pick 5051635
[dev 424b6ee] bug fixed
Date: Tue Jun 9 17:40:56 2020 +0800
Committer: Wang <zhong@cnt01.local>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:
git config --global user.name "Your Name"
git config --global user.email you@example.com
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 1 insertion(+)
这时 dev 的bug也修好了。
四、远程仓库
添加远程仓库
根据 github 的提示,添加 github 远程仓库
git remote add origin git@github.com:michaelliao/learngit.git
意思是添加一个远程仓库:
origin
,它的地址是git@github.com:michaelliao/learngit.git
, 这里用的是 ssh,你需要生成一个密钥,然后在github中添加进去。
推送到远程仓库
第一次推送,带上-u
参数,会将本地的分支推送到远程,并且和远程的分支关联起来
git push -u origin master # 第一次推送,-u;将本地 master 分支推送到远程 origin 上
git push origin master # 以后的简化操作
将本地分支和远程分支关联,有两种情况:
第一,本地有 dev
分支,远程仓库没有此分支:
# 两句话意思一样,第一句是第二句的简写
git push -u origin dev
git push --set-upstream origin dev
会在远程仓库创建一个分支 origin/dev 并和本地 dev 关联起来
第二,远程有 dev
分支,本地没有
git checkout -b dev origin/dev # 创建并克隆远程的dev分支到本地dev分支
git branch --set-upstream-to=origin/dev dev # 设置 dev 分支和远程 origin/dev 分支连接
查看远程仓库信息
git remote
查看更详细内容
git remote -v
查看远程的分支
git branch -r
克隆远程仓库
默认克隆master
git clone git@github.com:michaelliao/gitskills.git
克隆分支
git checkout -b dev origin/dev # 创建并克隆远程的dev分支到本地dev分支
设置 dev 分支和远程 origin/dev 分支连接,才能git pull下来
git branch --set-upstream-to=origin/dev dev
多人协作:
- 首先,可以试图用
git push origin
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
拉取下来,然后合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin
推送就能成功!
如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/<branch-name>
。
rebase(http://gitbook.liuhui998.com/4_2.html)
- 合并本地的几个commit记录(最好只合并本地的,未push的记录,如果某个记录已经 push 了,然后本地 rebase 时包含了这个记录,push时会有问题)
git rebase -i HEAD~2 # 合并最近的2条 commit 记录;
git rebase -i <commitID> # 从当前HEAD一直合并到某个commitID上。
输入上面的命令后,会出现一个vi编辑文本窗口,注意前两行:pick [commit ID] [commit msg]
按下 i 键,编辑文本,将第二行的 pick
改成 s
,然后 Esc 保存退出::wq
, 这样可以将 v3 这条记录,合并到 v2 上。
其实底下的说明文字已经很清楚了:s,代表将此 commit 合并的上一个提交上。
pick 8ee8c5c v2
pick 3d134f7 v3
# Rebase d2f44c9..3d134f7 onto d2f44c9 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
保存退出后,会继续出现一个 vi 编辑文本框,因为你之前提交了两次,现在合并成一次,所以现在给你个机会让你修改 commit message,如果不需要修改,可以直接:wq
退出,会保留两次 commit msg.
- 合并两个分支记录
正常的 merge 操作,可以合并两个分支,但是在使用git log --graph
时,可以看出分支分叉,然后合并的操作。如果不想要这个操作,可以这么做:
前提:假设 master 最新的提交是 v3, dev 分支基于 v3 分出来的,然后 dev 前向提交了一次,走到了 v4; master 也提交了一次,走到了 v5.
$ git log
commit 58e90228a37f03b23fb6168efa08849441facd48 (HEAD -> dev)
Author: wztshine <none>
Date: Fri Oct 8 22:14:50 2021 +0800
v4
commit 3d134f77cbcce2c09c499c85a6526dd8c058d630
Author: wztshine <none>
Date: Fri Oct 8 21:40:25 2021 +0800
v3
commit 8ee8c5c4215ed5da08af8d8c46fd096c9788f07e
Author: wztshine <none>
Date: Fri Oct 8 21:40:14 2021 +0800
v2
commit d2f44c928add3708a7897c446f028d75871e5f94
Author: wztshine <none>
Date: Fri Oct 8 21:40:01 2021 +0800
v1
==================================
$ git log
commit bd27e9865acab57e505e08807da2b5dd1c398022 (HEAD -> master)
Author: wztshine <none>
Date: Fri Oct 8 22:15:26 2021 +0800
v5
commit 3d134f77cbcce2c09c499c85a6526dd8c058d630
Author: wztshine <none>
Date: Fri Oct 8 21:40:25 2021 +0800
v3
commit 8ee8c5c4215ed5da08af8d8c46fd096c9788f07e
Author: wztshine <none>
Date: Fri Oct 8 21:40:14 2021 +0800
v2
commit d2f44c928add3708a7897c446f028d75871e5f94
Author: wztshine <none>
Date: Fri Oct 8 21:40:01 2021 +0800
v1
此时想要合并两个分支,并且 git log --graph 命令中不出现分叉:先切换到 dev,将 master rebase过来,然后切换到master,将dev合并过来。
git checkout dev
git rebase master
git checkout master
git merge dev
假设你基于远程仓库 origin
创建一个新的分支 mywork
, 然后你做了几次修改,但是与此同时 origin
也被人修改了,这时你想要合并这两条线。
如果正常合并 merge
, 会产生一条合并记录(分叉再汇合),如果使用rebase
$ git checkout mywork
$ git rebase origin
这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。
这样虽然你的分支线断掉了(插入了origin的更新),但是变成了一条线,没有分叉。
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决冲突;在解决完冲突后,用"git-add"命令去更新修改的冲突文件, 然后,你无需执行 git-commit,只要执行:
$ git rebase --continue
这样git会继续应用(apply)余下的补丁。
在任何时候,你可以用--abort
参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。
$ git rebase --abort
五、标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。
标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
创建标签
git checkout <branch> # 切换到分支
git tag v1.0 # 打标签
创建带有说明的标签,用-a
指定标签名,-m
指定说明文字
git tag -a v0.1 -m "version 0.1 released" 1094adb
列出标签
git tag
查看标签信息
git show <tag name>
通过commit id 打标签
git tag v0.9 f52c633
删除标签
git tag -d v0.1
标签推送到远程
git push origin v1.0
批量推送标签
git push origin --tags
删除远程标签
git tag -d v0.9 # 先删除本地
git push origin :refs/tags/v0.9
六、补丁
git format-patch命令,可以找出两个commit之间的差异部分,然后将差异部分提取成一个补丁。
现有这样一个提交记录:
$ git log
commit 40c728c7951d8c4e4b0b5442c017b6fc81948f02 (HEAD -> master)
Author: watao <exta>
Date: Wed Jun 30 12:46:37 2021 +0800
del c
commit bdbdddcb5ff4dd98d00dcfc5979d9085873cbc34
Author: wangzao <exte>
Date: Wed Jun 30 12:46:25 2021 +0800
del b
commit 0b2f5b080c1f5f2c379c02f50206a7c8396ffe12
Author: wano <e.cn>
Date: Wed Jun 30 12:46:14 2021 +0800
del a
commit c3ffc3f5d93882dbcf288b2174cbf0b7dd25388f
Author:
Date: Wed Jun 30 11:08:23 2021 +0800
a,b,c
1. 生成补丁
- 最近两次提交的补丁
$ git format-patch -1 # 生成一个补丁
0001-del-c.patch
- 两个commit之间的补丁
$ git format-patch c3ffc3f5d9..40c728c795 # 最初的提交和最后一个提交。'..'两边是commitID
0001-del-a.patch # 前面的序号越小,代表这个补丁的commit越早
0002-del-b.patch
0003-del-c.patch
- 某个commitID之前的n次补丁
$ git format-patch -2 40c728c795
0001-del-b.patch
0002-del-c.patch
2. 打补丁
git apply可以打补丁,git am同样可以打补丁。
- 检查补丁能否成功打上
$ git apply --check 0002-del-c.patch
error: c: No such file or directory # 因为当前没有c这个文件,所以这个"del c"的补丁,肯定打不上去
所以我们可以先创建一个c文件,或者将版本撤销到没有删除c文件之前的状态
$ touch c
$ git apply 0002-del-c.patch # 执行完后,发现c文件被删除了,也就是补丁生效了
- 补丁冲突失败
当文件有更新,产生冲突时,打补丁会失败,可以通过 --reject
参数,生成一个补丁的失败的对比文件,这时候可以根据这个差异文件,手动修改补丁冲突的部分
git apply 0001-edit-a.patch --reject # 失败的话,会生成一个 .rej 后缀的文件,记录了变动
$ cat a.rej
diff a/a b/a (rejected hunks)
@@ -0,0 +1,6 @@
+./t1/t2/t3/t4/t5/t6
+./t1/t2/t3/t4/t5
+./t1/t2/t3/t4
+./t1/t2/t3
+./t1/t2
+./t1
Windows配置github
-
注册github
-
安装git到本机
-
git命令窗口中配置用户名和邮箱:
-
–global
参数,表示你这台机器上所有的Git仓库都会使用这个配置 -
git config --global user.name “Your Name” git config --global user.email "email@example.com"
-
-
创建SSH key,直接三次回车
-
ssh-keygen -t rsa -C "your_email@youremail.com"
-
-
进入.ssh文件夹,里面有两个key, 其中
id_rsa.pub
是公钥,打开它,复制里面的内容,在github的设置里面,找到 SSH and GPG keys,添加就ok了-
$ cd ~/.ssh $ ls id_rsa id_rsa.pub known_hosts
-
-
测试是否连上
-
$ ssh -T git@github.com Warning: Permanently added the RSA host key for IP address '13.250.177.223' to the list of known hosts. Hi wztshine! You've successfully authenticated, but GitHub does not provide shell access.
-
others
重命名文件/文件夹
git mv name1 name2
自定义别名
给git命令起个别名,如 git status
= git st
; git reset HEAD
= git unstage
git config --global alias.st status
git config --global alias.unstage 'reset HEAD'
配置Git的时候,加上--global
是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
每个仓库的Git配置文件都放在.git/config
文件中,别名就在[alias]
后面,要删除别名,直接把对应的行删掉即可。而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中
[user]
name = “wztshine
email = xxxxxxxxx
[core]
autocrlf = true
[difftool "sourcetree"]
cmd = '' \"$LOCAL\" \"$REMOTE\"
[mergetool "sourcetree"]
cmd = "'' "
trustExitCode = true
[alias]
co = checkout
cm = commit
忽略特殊文件
有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status
都会显示Untracked files ...
,有强迫症的童鞋心里肯定不爽。
好在Git考虑到了大家的感受,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写.gitignore
文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
eg.
# git
.gitignore
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
# My configurations:
db.ini
deploy_key_rsa
常用过滤规则:
# 开头的是注释
/mtk/ 过滤整个文件夹
!/mtk/one.txt 不过滤某文件夹下某文件
*.zip 过滤所有.zip文件
/mtk/do.c 过滤某个具体文件
!*.zip 不过滤zip
最后一步就是把.gitignore
也提交到Git,就完成了!当然检验.gitignore
的标准是git status
命令是不是说working directory clean
。
使用Windows的童鞋注意了,如果你在资源管理器里新建一个.gitignore
文件,它会非常弱智地提示你必须输入文件名,但是在文本编辑器里“保存”或者“另存为”就可以把文件保存为.gitignore
了。
有些时候,你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore
忽略了:
$ git add App.class
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.
如果你确实想添加该文件,可以用-f
强制添加到Git:
$ git add -f App.class
或者你发现,可能是.gitignore
写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore
命令检查:
$ git check-ignore -v App.class
.gitignore:3:*.class App.class
Git会告诉我们,.gitignore
的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
git pull 和 git fetch 的区别
git fetch 后,本地库并没有变化,git fetch只会将本地库所关联的远程库的commit id更新至最新。
git pull 后,本地库更新至最新,git pull会将本地库更新至远程库的最新状态(最后一次commit id),而本地库所关联的远程库并没有变化。
提取两次commit的修改文件
压缩成一个包
git diff 9e483c619bb74391fb37c466bd0e364edf142685 f912640e943abeee2a3ce6b38aae9e7b2500861d --name-only | xargs tar -zcvf diff.tar.gz
解压
tar -zxvf diff.tar.gz
git commit --amend,补丁
假设这么一个场景:
你修改了一个bug,使用 git add
, git commit -m "fixed one bug"
之后,发现之前 add 的时候,漏掉了一个文件 A.py
,此时你可能下意识的有两种选择:
- 单独对
A.py
进行git add A.py
,git commit -m "add A.py"
的操作。但是这样做不好,因为会有两次commit记录 - reset上一次的commit记录,回退到之前的版本,然后对包括 A.py 在内的所有文件,再一次性 add,commit 一遍。缺点是费事,而且需要先把版本回退,再重新编辑修改,麻烦。
那有没有方法,可以直接重新commit一次,而又不出现两次commit记录呢?答案就是:git commit --amend
还是上面的例子,当你 commit 之后,发现漏掉了 A.py ,你可以
git add A.py # 将A.py添加到暂存区,等待 commit 提交
git commit --amend --no-edit # 提交暂存区的更改,在不改变上次commit信息的前提下,将上次和这次的commit合并,--no-edit意思是不修改上次的commit的信息
举个例子:
- 创建一个文件A.py,并提交:
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ touch A.py
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ git add .
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ git commit -m 'create A.py'
[main 2186bcc] create A.py
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 A.py
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ git log -1
commit 2186bccc891b30f321facda9aa27baf67c033afc (HEAD -> main)
Author: “wztshine <2419434353@qq.com>
Date: Wed May 19 22:33:13 2021 +0800
create A.py
- 发现忘记编辑A.py了,编辑一下A.py,补充提交,你会发现,提交信息还是上次的 “create A.py” ,也就是只有一次commit记录:
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ vi A.py
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ git add .
warning: LF will be replaced by CRLF in A.py.
The file will have its original line endings in your working directory
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ git commit --amend --no-edit
[main 7f1fe06] create A.py
Date: Wed May 19 22:33:13 2021 +0800
1 file changed, 1 insertion(+)
create mode 100644 A.py
wztshine@DESKTOP-DCBC2US MINGW64 ~/Desktop/PUA (main)
$ git log -2
commit 7f1fe06ca533a84b0ce711fce029b3a1c2af6a65 (HEAD -> main)
Author: “wztshine <2419434353@qq.com>
Date: Wed May 19 22:33:13 2021 +0800
create A.py
commit 0807084a3a601b4f4c6aa439c639a067898c9319
Author: “wztshine <2419434353@qq.com>
Date: Wed May 19 22:17:39 2021 +0800
add test1
补充:不加 --no-edit
,会弹出一个 vi 文本的编辑界面,第一行就是上次commit时写的备注,此时你可以修改第一行,来修改之前的备注,此界面操作模式和vi相同,编辑完成 :wq
退出即自动完成commit操作。
create A.py
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Wed May 19 22:33:13 2021 +0800
#
# On branch main
# Your branch is ahead of 'origin/main' by 2 commits.
# (use "git push" to publish your local commits)
#
# Changes to be committed:
# new file: A.py
-m 参数:
git commit --amend -m "new message" # 使用-m,会自动使用后面的 message 来替换之前commit时的备注信息。
给开源软件贡献代码
github 上想要给别人的仓库提交代码,需要:
- fork 别人的仓库到自己的仓库
- 从自己的仓库拉取修改,然后 push 到远程仓库
- 在自己的仓库中,提交 pull reqeust 合并到对方的仓库中
设置 git
怎么设置关联 git 和 github 上的仓库?
我们只能操控自己的远程仓库,如果想要修改别人的仓库,需要在 github
上 fork
别人的仓库,到自己的账号下,然后拉下来,进行修改,再提交到自己 fork 的仓库里。
免密拉取和提交代码有如下两种方式:
方式一:SSH
- 打开 git 命令行窗口,输入如下命令,然后敲击三次回车键,可以生成 ssh:
ssh-keygen -t rsa -C "your_email@youremail.com"
- 进入
.ssh
文件夹,里面有两个key, 其中id_rsa.pub
是公钥,打开它,复制文件里面的内容,在 github 账号的settings
里面,找到SSH and GPG keys
,添加就ok了
$ cd ~/.ssh
$ ls
id_rsa id_rsa.pub known_hosts
- 然后,当你想要拉取一个仓库的代码时,必须复制使用它的
SSH
链接地址,如:git@github.com:wztshine/learngit.git
方式二:https + token
设置了 ssh ,可以免密拉取和提交代码到远程仓库,如果使用仓库的 https
链接地址,则必须每次提交都需要输入用户名和密码,而 github 又不再支持密码登陆模式了,所以需要设置 token
点击你的 github 账户,选择 Settings -> Developer settings -> Personal access tokens -> Generate new token
, 然后输入 token 名字,设置它的过期时间,以及选择这个 token 的权限,就可以生成一个 token 了,然后复制这个 token。拉取 https 地址时这样写:
git clone https://TOKEN@github.com/wztshine/learngit.git
在
https://
后面加上你自己刚生成的token字符串, 并紧跟一个@
符号。这样你以后 push 或者 pull 的时候,github 就会根据你的 token 以及这个 token 的权限,来决定是否有权利去提交代码。