git 备忘录

目录

0. 本文目的

公司里用svn管理代码,但在个人开发机上管理代码用git更方便,因为:1)本地就可以执行commit/checkout,不需要连到服务器;2)我的代码修改版本太多,主要给自己看。

主要是在Git Bash中敲基本的git命令,辅助一些GUI工具,因为:1)Git Bash能正确显示中文,cmd不能; 2)比较目录等情况下,GUI软件效率高。

1. git使用GUI比较程序

一个典型的问题是:如何比较两次git commit / 两个branch 下的整个repo?

配置

  • 需要安装比较工具,我用的是Beyond Compare4。在没有使用git的时候,Beyond Compare的易用性也让我在不同版本代码的比较和合并中颇有收益。

  • 还需要在git中配置Beyond Compare

Beyond Compare 4注册码:

w4G-in5u3SH75RoB3VZIX8htiZgw4ELilwvPcHAIQWfwfXv5n0IHDp5hv
1BM3+H1XygMtiE0-JBgacjE9tz33sIh542EmsGs1yg638UxVfmWqNLqu-
Zw91XxNEiZF7DC7-iV1XbSfsgxI8Tvqr-ZMTxlGCJU+2YLveAc-YXs8ci
RTtssts7leEbJ979H5v+G0sw-FwP9bjvE4GCJ8oj+jtlp7wFmpVdzovEh
v5Vg3dMqhqTiQHKfmHjYbb0o5OUxq0jOWxg5NKim9dhCVF+avO6mDeRNc
OYpl7BatIcd6tsiwdhHKRnyGshyVEjSgRCRY11IgyvdRPnbW8UOVULuTE
  • Beyond Compare提示到期
    如果Beyond Compare提示评估到期,卸载、删注册表、重装后,还是提示评估到期,那么:
    修改C:\Program Files\Beyond Compare 4\BCUnrar.dll ,这个文件重命名或者直接删除

在Git Bash中编辑~/.gitconfig,确保有如下字段:

[diff]
        tool = bc4
[difftool "bc4"]
    cmd = "\"D:\\soft\\Beyond Compare 4\\BCompare.exe\" \"$LOCAL\" \"$REMOTE\""
[merge]
        tool = bc4
[mergetool "bc4"]
    cmd = "\"D:\\soft\\Beyond Compare 4\\BCompare.exe\" \"$LOCAL\" \"$REMOTE\""

注意其中Beyond Compare的路径写法,反斜杠、引号都不能少;并且应该使用cmd而不是path

使用

比较两次commit:

git difftool commit_id1 commit_id2 -d

其中-d表示以目录形式比较,而不是默认的“逐文件比较”。

比较两个分支,例如master和develop分支:

git difftool origin/master origin/develop -d

2. git中文件的几种状态

在执行git add后,在修改文件后,在git commit后,使用git status查看状态,感觉有点晕,于是仔细研究下git的状态:

针对单个文件,可以粗略分成2个大的状态:

  • untracked,也就是没有被git跟踪,只要文件存在,并且没有被git add过,就是untracked状态
  • tracked,被git跟踪,只要被git add过(并且没有被git remove过),就是tracked状态。它可以进一步细分:
    • unmodified,没有修改,是一个文件指被git add和git commit过,而当前working area中的该文件与commit时一致
    • (not staged) modified,命令行下显示为红色,是指文件被git commit过,并且现在在工作区被修改了,但是没有通过git add放到staging area(暂存区)
    • modified,命令行下显示为绿色,是指文件有被git commit过,现在在工作区被修改了,并且也被git add了,但是没有被git commit过
    • new file,命令行下显示为绿色,是指文件第一次被git add(而处于staging area),而没有被git commit

相应的,对于整个工程的文件,有3个区域:

git diff和git diff --cached

输入git diff,查看到的是工作区和暂存区的不同

输入git diff --cached,查看到的是暂存区和HEAD的不同。

如下测试可以验证:

mkdir -p /tmp/git-demo
cd /tmp/git-demo
git init .
echo "#include <stdio.h>" >> main.c
echo "this is the readme" >> readme.md
git add .
git commit -m "first commit"
echo "int main(){printf("hello\n"); return 0;}" >> main.c
echo "add a new line" >> readme.md
git add main.c
git diff
git diff --cached

也即:首先把main.c和readme.md执行git add和git commit;然后分别修改main.c和readme.md,但是只git add main.c;这时候git diff只能看到readme.md的不同,是working area和stage的比较;此时输入git diff --cached只能看到main.c的不同,是stage和HEAD的比较。

git difftool和git mergetool

但凡用到git diff的地方,包括git diff本身,以及带的其他参数例如git diff --cached,都可以把diff换成difftool,这样的话就会使用在~/.gitconfig中配置的diff的图形界面工具来执行比较。e.g.:

git difftool -y
git difftool --cached -y

其中-y表示yes,不要询问我是否用我配置的GUI工具(例如beyond compare)来打开,直接打开就是了。

类似的,git merge也有对应的git mergetool,只要先前在~/.gitconfig中配置过mergetool即可。实际上,beyond compare也可以做mergetool,我的difftool和mergetool都是它。

查看版本差异/版本回退/撤销回退

这里考虑的是整个工程的所有代码文件。

例如有3次commit,现在(在commit_id3的基础上,有代码修改!)突然发现代码有bug,而第二次的commit当时测试是没有bug的,那么我最新一次(第三次)commit中肯定是写了bug的,就希望从这次commit中新增的代码中找出来。

此时,如果要回退版本,因为working area有代码没有commit,应当add并commit,否则reset后回不来

此时有三种选择:

  • 查看两个版本之间的差异:
    git difftool -y commit_id2 commit_id3
  • 把working area,(从commit_id3)切换回commit_id2,并且保证以后能再切换回commit_id3
    git reset --hard commit_id2
  • commit_id2切换回commit_id3
    先使用git reflog查看得到commit_id2的值,然后git reset --hard commit_id3

3. 单个文件撤销工作区修改

git checkout -- filename

4. 查看远端(remote)地址

有时候在同一目录下,git clone了好几份类似的代码,为了区分它们,可以把它们的下载地址放在一个readme.txt中,但是仍然不方便。

简单方便的方法是:进入各自repo的目录,查看remote:

cd hed
git remote origin show

其中origin是默认的远端名字,就像master是默认的分支一样。结果如下:

⚡ git remote show origin 
* remote origin
  Fetch URL: https://github.com/zeakey/hed
  Push  URL: https://github.com/zeakey/hed
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

5. 删除untracked状态的文件、目录

  • 删除单个untracked状态的文件
git clean -f  xxx

其中-f表示force,强制删除。因为git的配置中clean.requireForce默认为true,所以必须加-f才能正常执行清除(个人猜测:用来防止小白误删文件)

  • 删除所有untracked状态的文件
git clean -f
  • 删除所有untracked状态的文件、目录
git clean -df

6. 从本地文件系统的仓库中clone

情景:项目中用到一个开源项目(比如opencv),它的代码仓库比较大,而又需要经常使用它的不同分支,那么最好把它各个分支都checkout出来。每个branch都从github上clone下来,会非常慢,也没有必要

首先要明确下,git clone可以指定-b branch_name来克隆指定的branch,而如果不指定的话其实也只是克隆一个分支,只不过是HEAD对应的分支,最常见的情况下是master分支。

其次明确下,git clone可以从本地文件系统进行:

git clone file:///path/to/local/machine/repo

#或者:
git clone /path/to/local/machine/repo

因此需要注意,从本地文件系统的repo进行git clone,只能指定本地文件系统repo中的本地分支。

完整步骤举例:

cd ~/work
git clone https://github.com/opencv/opencv

# 查看下有哪些分支
git branch -a

# 把所有的远程分支,都在本地创建同名分支
# 参考:
git branch -r | grep -v '\->'  | grep -v `git branch | awk '/\*/ { print $2; }'`| while read remote; do git branch --track "${remote#origin/}" "$remote"; done


# 切换到其他工作目录,从本地文件系统的repo clone,速度飞起
cd ~/work/
git clone ~/work/opencv opencv_2.49  -b  2.4

7. 设置git命令别名(alias)

~/.gitconfig添加:

[alias]
    co = checkout
    ci = commit
    st = status
    br = branch
    hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
    type = cat-file -t
    dump = cat-file -p

8. git checkout xxx后,git log显示不全?

需要加上branch的名字。e.g.:

git log master

git hist master

9. git打标签(tag)

tag和branch的区别: branch是一系列的commit,tag则是一个commit。

通常是对历史版本中某个commit打标签,步骤:

git hist  #查看提交情况,用来获取commit id
git co xxxxx # 切换到某个commit
git tag tag_name #打标签,名字是tag_name

10. git reset和git co的区别?

不太懂,挖坑代填。

11. git撤销修改

分好几种情况

1. 撤销工作区修改

git  checkout  file_name  #检出某个文件

git checkout . #整个目录都从新检出

2. 撤销暂存区修改

git reset file_name

3. 撤销提交

git revert HEAD

其实我对git revert还不怎熟悉

12. 从内网机器克隆代码

从内网linux主机克隆到本地windows机器,使用ssh协议

git clone ssh://zz@172.xx.xx.xx:/home/zz/work/cnn-infer-testbed

从内网Windows主机克隆代码

万能的方法是,在windows主机上临时开启git daemon,类似于python开启http server

git daemon --base-path=<path_to_folder_containing_project_folder> --export-all

然后在本地机器(client)上克隆:

git clone git://<local ip>/<project name>

ref: How to git clone a repo in windows from other pc within the LAN?

注意:如果是从Windows主机clone到Linux上,在Linux上修改并commit后,无法git push回到Windows,见git server hosting using git:// protocol, unable to set SO_KEEPALIVE, no such file or directory。解决方案:在Windows上的repo中添加remote为Linux上的repo地址,e.g:

git remote add linux-machine ssh://zz@172.xx.xx.xx:/home/zz/work/yyy
git pull linux-machine master

13. tag操作

给当前commit添加tag:

git tag my_tag_name

给已有tag改名字:(则对应的commit此时有两个tag)

git tag new old

删除已有tag:

git tag -d tag_name

给远程的tag改名字,步骤:

git tag new old

git tag -d old

git push origin :refs/tags/old

git push --tags

添加tag,比较好的做法

git tag -a 1.6.0.4011 -m "hi3559"

查看tag及message

git tag -l -n

14. 忽略文件权限(mode)的差异

比如我在Linux上git clone的代码,随后整个仓库拷贝到Window上,git st看到很多文件被改了,但是我实际上没有改,原因是文件的mode在复制的时候被改变了:

$ git diff tools/script/test_android.sh
diff --git a/tools/script/test_android.sh b/tools/script/test_android.sh
old mode 100755
new mode 100644

解决办法也很简单:忽略mode的差异

git config --global --add core.filemode false

在commit中查找

git hist --grep="feature"

既然是用grep,自然想到grep -i,invert模式,找到“非xxx”的内容:

git hist --grep="feature" --invert-grep

15. 规范书写git commit

规范的commit,排查问题方便,看起来也没管,是正规军的模样,例如:https://github.com/junluan/shadow/commits/master

每次git commit时,注释中有提示信息。通过设定git的commit.template来增加提示信息(而不是修改):

  • 修改~/.gitconfig,添加:
[commit]
    template = ~/.gitmessage
  • 新建~/.gitmessage,内容:
# <type>: (If applied, this commit will...) <subject> (Max 50 char)
# |<----  Using a Maximum Of 50 Characters  ---->|


# Explain why this change is being made
# |<----   Try To Limit Each Line to a Maximum Of 72 Characters   ---->|

# Provide links or keys to any relevant tickets, articles or other resources
# Example: Github issue #23

# --- COMMIT END ---
# Type can be
#    feat     (new feature)
#    fix      (bug fix)
#    refactor (refactoring production code)
#    style    (formatting, missing semi colons, etc; no code change)
#    docs     (changes to documentation)
#    test     (adding or refactoring tests; no production code change)
#    chore    (updating cmake scripts etc; no production code change)
# --------------------
# Remember to
#    Capitalize the subject line
#    Use the imperative mood in the subject line
#    Do not end the subject line with a period
#    Separate subject from body with a blank line
#    Use the body to explain what and why vs. how
#    Can use multiple lines with "-" for bullet points in body
# --------------------
# For more information about this template, check out
# https://gist.github.com/adeekshith/cd4c95a064977cdc6c50

ref: 优雅的提交你的 Git Commit Message

16. git clone使用https协议还是ssh协议,或者git协议?

参考 学习 git clone 几种不同的协议,简而言之:

  • git clone https://gitlab.com/xxx/yyy 适合:初学者,或者克隆的是开源公共项目

  • git@gitlab.com:xxx/yyy.git 适合:项目maintainer,项目管理员,通常搭配ssh key,先生成和粘贴ssh公钥到gitlab上,第一次clone输入凭据,以后免密码

其他的暂时不打算用。

17. 管理ssh key

管理多个ssh key

例如,同时需要使用github, 公司gitlab服务器,gitee

每个平台上最好分别设定ssh key,方便管理。

参照这篇:GitLab配置ssh key,直接照着做好了,就先不粘贴整理了。

粘贴ssh key遇到错误:Fingerprint 已经被使用 Fingerprint cannot be generated

通常是用xshell、git-bash、scure-crt等终端连接到远程服务器时,cat查看ssh公钥内容时候有多余的换行,拷贝到gitlab的网页上后无法被正确识别。

其实可以看出来的,正常的key是会自动帮你填写一个key的名字的,有多余空行的话就不自动生成key的名字。

解决办法就是从samba打开公钥文件然后拷贝粘贴。

18. 存储密码

有时候代码仓库是用https协议的,没法改成ssh协议,每次输入密码很烦。设置记住密码即可:

git config --localcredential.helper store

如果要全局设定,则改用global参数:

git config --global credential.helper store

19. 使用git rebase

git rebase的作用,是把当前分支的commit都临时取消掉,然后当前分支更新到指定分支的最新commit,在这个“最新”commit上,把本分支刚刚弄成patch的commit给“贴回去”,如果有冲突则需要手动解决一下。
好处:相比较merge操作而言,避免了一次不必要的commit记录。

让当前分支变基(rebase)为origin远端的master分支:

git rebase origin/master

20. 使用rebase和merge的场景

下游分支(featrue1)更新上游分支(master)内容的时候用rebase
上游分支合并下游分支内容的时候使用merge

ref: Git16 Rebase

个人的见解是:
如果要合并两个分支的代码,如果没有冲突,用哪个都可以,需要考虑的仅仅是“多引入一个commit是否有必要”;
如果要合并的两个分支的代码,有冲突,或者说有可能有冲突,那么根据冲突的优势劣势方来确定:

  • 如果被合并进来的分支,在冲突的代码中占主导优势,那么当前branch应当是作出让步的一方。用git rebase。
  • 如果被合并进来的分支,处于劣势,一旦有冲突会优先改掉、干掉被合并进来的这个分支的代码,那么应该用git merge

21. git实践

  1. 利用orphan分支,在同一个repo中并行管理两个项目的代码
  2. 两个本地repo共用一个remote,独立开发和管理:基于branch和remote branch,以及git push默认分支的设定
  3. 利用git rebase和git squash,在git push到remote前压缩commit节点(参考:https://www.cnblogs.com/dsxniubility/p/4460834.html)

22. 修改先前的本地commit的author

首先

git config --global user.name "xxx"
git config --global user.email "xxx@yyy.com"

然后:

git commit --amend --reset-author

23. COMMIT_EDITMSG文件出现问题

git commit --amend时提示:

.git/COMMIT_EDITMSG" E513: 写入错误,转换失败 (请将 'fenc' 置空以强制执行

解决办法:删除.git/COMMIT_EDITMSG文件。然后退出现有git commit的vim窗口,重新git commit --amend即可。

在操作git中有时候会提示 Unlink of file '......' failed. Should I try again?

原因是你工作目录有某些文件正在被程序使用,这个程序多半是Idea,VS或者eclipse,当然也可能是其他程序

解决方案不是简单的选择y或者n,而是关闭IDE,让IDE把这些文件释放掉

ref: https://www.cnblogs.com/wormday/p/git_unlink_of_file_failed_should_i_try_again.html

25. git遭遇文件名过长

error: unable to create file xxx Filename too long
出现在Windows下,git repo中的文件名绝对路径过长,创建失败。

解决办法:

git config --global core.longpaths true

26. git reset --hard后恢复暂存区文件

执行git reset --hard后,暂存区(先前执行过git add但是没commit)的文件变化就找不到了。实际上可以找到,不过比较hack,也不适合修改的文件很多的情况。

find .git/objects/ -type f | xargs.exe ls -lt | sed 5q,此命令找到最近5次git add的文件的内容;

git cat-file -p hash_value 查看对应哈希值的文件内容到屏幕上,可以配合重定向符号写入到文件。

https://blog.csdn.net/yeluosc/article/details/76690678

26. git reset三种模式(--hard --soft --mixed)的含义、差别

通用命令格式:

git reset --<reset_mode>  commit_id

其中reset_mode--hard, --soft--mixed三种取值,--mixed是默认值;
commit_id是提交记录中的某一个哈希值,也可以是HEADHEAD^1这样的表达式。

git reset的三种模式,共同点是把本地仓库(repo)的HEAD切换到commit_id,不同点是“工作区、暂存区是否也跟着改变到commit_id中文件对应状态:

  • git reset --hard: 工作区、暂存区、本地仓库,都被切换到commit_id状态
  • git reset (--mixed): 暂存区、本地仓库被修改到commit_id状态,工作区不变
  • git reset --soft:只有本地仓库被切换到commit_id状态,工作区、暂存区都不变

27. 查看最近一次commit修改了哪些文件?

git log -1 --stat

28. 恢复删除的branch

Git会自行负责分支的管理,所以当我们删除一个分支时,Git只是删除了指向相关提交的指针,但该提交对象依然会留在版本库中。

因此,如果我们知道删除分支时的散列值,就可以将某个删除的分支恢复过来。在已知提交的散列值的情况下恢复某个分支:

git branch <branch_name> <hash_val>

如果我们不知道想要恢复的分支的散列值,可以用reflog命令将它找出来。如:

ref: Git删除分支/恢复分支

29. 已经add过的文件,可以ignore吗?

如果仅仅是add了,但是没有commit过,相对容易做到。

原理:从暂存区取消记录文件/文件夹。

也就是:

git rm --cached file.txt   # 取消track单个文件
git rm --cached imgs -r    # 取消track单个文件夹

30. git clone后打开文件显示乱码

通常是如下几个条件共同产生的:

  • 在Windows下编写的代码
  • 代码里有中文
  • 代码文件格式不是UTF-8

解决:批量转换为UTF-8编码:

find . -name '*.cpp' -exec enca -L zh_CN -x UTF-8 {} \;
find . -name '*.h' -exec enca -L zh_CN -x UTF-8 {} \;

31. git add仅添加已追踪的文件

git add -u即可

在git中有好多的指令,但是今天这几个指令就很容易忘记而且还容易混淆
git add -u <==> git add –update
提交所有被删除和修改的文件到数据暂存区

git add .
提交所有修改的和新建的数据暂存区

git add -A <==> git add –all
提交所有被删除、被替换、被修改和新增的文件到数据暂存区

来源:https://blog.csdn.net/dayewandou/article/details/78513578

32. 使用git rebase的一个典型场景

git checkout -b dev
echo "hello" >> info.txt
git add .
git commit -m "add sth"
git checkout master
git merge dev

33. git使用socks代理加速

开启ss后查看端口,例如我是1080,则:

git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

然后就能高速使用git下载源码了。

34. 用gitolite搭建git服务器

2015-08-21 23:33

心血来潮的先在本地的fedora-server上装配了起来。
用gitolite搭建git服务器,作为代码版本控制server。gitolite比较流行,官方文档齐全。

fedora22下配置gitolite

一台server:我使用fedora22-server

依赖项:perl-devel, git-core, openssh

主要参考git服务器的建立——Git折腾小记

可能遇到的问题:

Can't locate Time/HiRes.pm in @INC (@INC contains: /home/git/gitolite/src/lib /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .) at /home/git/gitolite/src/lib/Gitolite/Common.pm line 76.

需要安装perl-devel:

sudo dnf install perl-devel

ssh公钥的设定

workstation上的gitolite设定好了,给用户使用的时候,用户每次都输入密码不方便,一个策略是使用ssh-key。通过在客户端上生成rsa的公钥,上传到gitolite-admin这个repo的keydir中,并以用户名.pub形式命名,然后在此repo的conf目录中的配置文件中对指定repo进行读写权限的设定。
具体设定的语法规则,可以去查看gitolite的manual。
值得注意的一点是:在添加rsa的公钥文件后,请git add keydir,否则这个文件没有被track,在配置文件中的配置也就不会生效。

CentOS7下gitolite3的配置

# 先确保添加了epel的repo
yum install gitolite3

按照/usr/share/doc/gitolite-3/下的readme文档进行配置,出了点问题:配置到各种git config --global后,要git clone gitolite-admin了,一直提示没有权限。ssh-key也添加了。google一番发现:ref

[root@dlp ~]# su - gitolite3
-sh-4.2$ ssh-keygen -f ~/.ssh/gitadmin 
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): # set passphrase
Enter same passphrase again: # confirm
Your identification has been saved in /var/lib/gitolite3/.ssh/gitadmin.
Your public key has been saved in /var/lib/gitolite3/.ssh/gitadmin.pub.
The key fingerprint is:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx gitolite3@dlp.server.world
The key's randomart image is:
-sh-4.2$ gitolite setup -pk ~/.ssh/gitadmin.pub 
Initialized empty Git repository in /var/lib/gitolite3/repositories/gitolite-admin.git/
Initialized empty Git repository in /var/lib/gitolite3/repositories/testing.git/
-sh-4.2$ vi ~/.ssh/config
# create new
# any name you like
host GitServer
    user gitolite3
    # Git server's hostname or IP address
    hostname 10.0.0.30
    port 22
    # secret key
    identityfile ~/.ssh/gitadmin
-sh-4.2$ chmod 600 ~/.ssh/config 
-sh-4.2$ git config --global user.name "gitolite3" 
-sh-4.2$ git config --global user.email "gitolite3@server.world" 
-sh-4.2$ git config --global push.default simple
# clone admin repository to finish setup
-sh-4.2$ git clone ssh://GitServer/gitolite-admin 
Cloning into 'gitolite-admin'...
The authenticity of host '10.0.0.30 (10.0.0.30)' can't be established.
ECDSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.30' (ECDSA) to the list of known hosts.
Enter passphrase for key '/var/lib/gitolite3/.ssh/gitadmin':
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.

35. git获取所有分支(fetch all branches)

在StackOverFlow上的问答: How to fetch all Git branches

可能会遇到提示:'fatal: A branch named 'origin/master' already exists.'

解决办法:用如下命令:

git branch -r | grep -v '\->'  | grep -v `git branch | awk '/\*/ { print $2; }'`| while read remote; do git branch --track "${remote#origin/}" "$remote"; done

36. git clone pytorch或caffe速度慢

可以从gitee导入github repo,而pytorch的话,submodule比较多,也要导入。

我在gitee的两个账号 aczz 和 arczz,里面有很多submodule,可以考虑试试。不过可能比较旧了。

37. 可以只fetch某一次commit吗

场景:希望学习某个repo是如果写出来的,则新建一个本地空repo(git init),添加remote后fetch,再cherry-pick即可。

举例:

mkdir dev-easycnn
cd dev-easycnn
git init
git remote add origin https://gitee.com/aczz/EasyCNN
git fetch origin
git cherry-pick bf22931

38. 创建orphan分支

在一个已有commit的repo中创建orphan分支。

cd repo
git checkout --orphan dev
git rm -rf .

39. 显示本地分支和远程分支的跟踪关系

git branch -vv

40. git 用--depth=1克隆后用git拉取更新

git pull --unshallow

或者

git fetch  --unshallow

41. git merge冲突时,用自己的或别人的代码

假设冲突的文件叫做 word.txt,则:

git checkout --ours word.txt  # 使用我们的代码,也就是merge前的
git checkout --theirs word.txt # 使用“他们”的代码,也就是对面来的

此外还需要注意,git rebase阶段如果冲突,则ours和theirs的定义,和git merge时的定义,是相反的。。

ref: 化解冲突:git merge 与 git rebase 中的 ours 和 theirs

42. git stash 贮藏的使用

考虑这样的场景:
场景1:在master执行过git commit,随后改了一些内容,但是不足以(或不想)提交为一次commit(包括没有git add的,也包括没有git commit的),但此时又不得不切换到另一个分支做其他事情。当前分支的修改,怎样处理比较好?
场景2:把代码上传到了github等remote,然后在家里和公司两台电脑A和B上都可以展开工作,某天在公司电脑B上提交了代码到github,而回到家里A电脑执行git pull时,发现昨天因为家里网络不好,A电脑上有未曾git add的代码,并且这些修改也不想作为一次commit,而git pull则提示需要贮藏。

所谓贮藏,可以理解为当前git repo有一个stack,可以存储临时的更改。既然是stack,可以存放多个这样的修改。

基本用法步骤:

# 贮藏当前没有git add和没有git commit的修改
git stash # 或 git stash push

# 列出所有贮藏
git stash list

# 丢弃最近一次贮藏
git stash pop

# 应用一次贮藏。但是都是作为没有git add的效果(没有暂存)
git stash apply

# 应用一次贮藏,并且区分了是否有暂存的情况
git stash apply --index
posted @ 2020-07-19 16:52  ChrisZZ  阅读(554)  评论(0编辑  收藏  举报