Git常用命令

mac2024-03-12  28

Git流行的GUI客户端:https://git-scm.com/downloads/guis

1、安装 Git

$ sudo apt-get install git

2、配置工具

为所有本地仓库配置用户信息。 (1)设置提交代码时用的用户名

$ git config --global user.name "[name]"

(2)设置提交代码时用的邮件地址

$ git config --global user.email "[email address]"

(3)设置命令行输出的颜色

$ git config --global color.ui auto

3、创建仓库,并初始化Git

第一种方式:$ git init 执行了git init初始化后,当前文件夹的文件都将置于git管理工具的管理与跟踪当中。这个命令会在当前目录下生成.git文件夹(更多关于.git文件夹的内容请参考《.git目录里的目录的作用》),如果不要git管理了,直接删除这个.git目录即可。

# 创建一个目录作为创建Git仓库的目录,方便管理 ~$ mkdir MyGit # 进入目录 ~$ cd MyGit # 核心命令,初始化仓库,执行完,就成功创建仓库了,会生成一个.git的隐藏目录 ~/MyGit$ git init Initialized empty Git repository in /home/kyun/MyGit/.git/ # 查看.git目录 ~/MyGit$ ls -a . .. .git ~/MyGit$ cd .git ~/MyGit/.git$ ls branches config description HEAD hooks info objects refs

所有对通过git命令添加到此文件夹中的文件的所有修改都会被跟踪到。这个文件夹你想放什么都可以。

我们再来讲一个与Android项目更密切相关的吧: 1、首先,我们在某个目录下创建一个项目 2、打开项目目录,进行Git管理初始化

~$ cd /home/kyun/Repository/MyFirstProject ~/Repository/MyFirstProject$ git init Initialized empty Git repository in /home/kyun/Repository/MyFirstProject/.git/

那么项目中通过git命令或在android studio中操作添加的文件的文件都可以被有效跟踪起来。当然上面这一步也可以在Android studio中操作,完成git的初始化:

第二种方式:$ git clone [url]

~$ git clone https://github.com/wongkyunban/ReadSMS.git Cloning into 'ReadSMS'... remote: Enumerating objects: 95, done. remote: Counting objects: 100% (95/95), done. remote: Compressing objects: 100% (66/66), done. remote: Total 95 (delta 12), reused 95 (delta 12), pack-reused 0 Unpacking objects: 100% (95/95), done. ~$ ls -a . .. ReadSMS ~$ cd ReadSMS ~/ReadSMS$ ls -a . app .git gradle gradlew .idea .. build.gradle .gitignore gradle.properties gradlew.bat settings.gradle ~/ReadSMS$ cd .git ~/ReadSMS/.git$ ls branches description hooks info objects refs config HEAD index logs packed-refs

分支

分支是Git的重要组成部分。我们所做的任何代码提交都将提交到当前我们签出的分支上。使用git status命令可以查看我们当前在哪个分支及相关的状态信息。

查看当前目录所在的分支: ~/Repository/MyFirstProject$ git status On branch master 创建分支 $ git branch [branch-name]

举例:

# 对于刚刚创建的仓库要进行一次提交,提交前要将当前文件夹的文件加入到git管理中来 ~/Repository/MyFirstProject$ git add . # 提交 ~/Repository/MyFirstProject$ git commit -m "init" # 创建分支 ~/Repository/MyFirstProject$ git branch MyFirstProject01 ~/Repository/MyFirstProject$ git status On branch master nothing to commit, working tree clean # 切换分支 ~/Repository/MyFirstProject$ git checkout MyFirstProject01 Switched to branch 'MyFirstProject01' ~/Repository/MyFirstProject$ git status On branch MyFirstProject01 nothing to commit, working tree clean

注意:创建新支时,在当前分支上去是做增量的。举个例子: 1、如果当前分支是master分支,那么在当前分支下创建分支,就会看到新分支的内容一开始时,与master分支是一样的。 2、如果当前分支是MyFirstProject01,那么在当前分支下创建分支,就会看到新分支的内容,在一开始时,与MyFirstProject01分支是一样的。

# 在当前分支MyFirstProject01下创建新分支MyFirstProject03 ~/Repository/MyFirstProject$ git status On branch MyFirstProject01 # 分支MyFirstProject01的内容 ~/Repository/MyFirstProject$ ls app gradle gradlew local.properties readme.txt build.gradle gradle.properties gradlew.bat MyFirstProject.iml settings.gradle # 创建新分支MyFirstProject03 ~/Repository/MyFirstProject$ git branch MyFirstProject03 # 切换MyFirstProject03分支 ~/Repository/MyFirstProject$ git checkout MyFirstProject03 M readme.txt Switched to branch 'MyFirstProject03' ~/Repository/MyFirstProject$ git status On branch MyFirstProject03 # 可以看到MyFirstProject03初始化时是MyFirstProject01的内容, # 以后MyFirstProject03分支就是在MyFirstProject01的基础上做增量变化 ~/Repository/MyFirstProject$ ls app gradle gradlew local.properties readme.txt build.gradle gradle.properties gradlew.bat MyFirstProject.iml settings.gradle ~/Repository/MyFirstProject$ git add readme.txt ~/Repository/MyFirstProject$ git commit readme.txt -m "init 03" [MyFirstProject03 6a0e145] init 03 1 file changed, 1 insertion(+), 1 deletion(-) # 我们切换到master分支,再创建一个新分支MyFirstProject04,这个分支将以master分支为基础,做增量变化。 ~/Repository/MyFirstProject$ git checkout master Switched to branch 'master' kyun@kyun-HP-348-G3:~/Repository/MyFirstProject$ ls app gradle gradlew local.properties settings.gradle build.gradle gradle.properties gradlew.bat MyFirstProject.iml # 创建一个新分支MyFirstProject04 ~/Repository/MyFirstProject$ git branch MyFirstProject04 # 切换到分支MyFirstProject04 ~/Repository/MyFirstProject$ git checkout MyFirstProject04 Switched to branch 'MyFirstProject04' # MyFirstProject04分支的初始内容与master分支是一样的,它将以master分支为基础,做增量变化 ~/Repository/MyFirstProject$ ls app gradle gradlew local.properties settings.gradle build.gradle gradle.properties gradlew.bat MyFirstProject.iml 切换分支 $ git checkout [branch-name]

例子如上例所示

合并分支 $ git merge [branch]

这个合并功能是把其他分支合并到当前分支来,也就是说合并只对当前分支有影响。 举个例子:

# 当前已有一个分支MyFirstProject01 ~/Repository/MyFirstProject$ git status On branch MyFirstProject01 nothing to commit, working tree clean # 再创建一个分支MyFirstProject02 ~/Repository/MyFirstProject$ git branch MyFirstProject02 # 切换到分支MyFirstProject02 ~/Repository/MyFirstProject$ git checkout MyFirstProject02 Switched to branch 'MyFirstProject02' # 在分支MyFirstProject02增加一个文件readme.txt ~/Repository/MyFirstProject$ touch readme.txt # 向文件readme.txt输入内容 ~/Repository/MyFirstProject$ echo Hello Branch MyFirstProject02 > readme.txt # 把文件readme.txt添加入git管理 ~/Repository/MyFirstProject$ git add readme.txt # 提交readme.txt文件到版本库 ~/Repository/MyFirstProject$ git commit readme.txt -m "init readme.txt" [MyFirstProject02 b645898] init readme.txt 1 file changed, 1 insertion(+) create mode 100644 readme.txt ~/Repository/MyFirstProject$ ls app gradle gradlew local.properties readme.txt build.gradle gradle.properties gradlew.bat MyFirstProject.iml settings.gradle # 切换到分支MyFirstProject01,然后把MyFirstProject02分支合并过去 ~/Repository/MyFirstProject$ git checkout MyFirstProject01 Switched to branch 'MyFirstProject01' # 合并MyFirstProject02分支前 ~/Repository/MyFirstProject$ ls app gradle gradlew local.properties settings.gradle build.gradle gradle.properties gradlew.bat MyFirstProject.iml # 合并MyFirstProject02分支到MyFirstProject01来 ~/Repository/MyFirstProject$ git merge MyFirstProject02 Updating 287c845..b645898 Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 readme.txt # 合并MyFirstProject02分支后 ~/Repository/MyFirstProject$ ls app gradle gradlew local.properties readme.txt build.gradle gradle.properties gradlew.bat MyFirstProject.iml settings.gradle # 当前分支状态 ~/Repository/MyFirstProject$ git status On branch MyFirstProject01 Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: readme.txt no changes added to commit (use "git add" and/or "git commit -a") # 从MyFirstProject02合并过来的文件 ~/Repository/MyFirstProject$ cat readme.txt Hello Branch MyFirstProject02 删除分支 $ git branch -d [branch-name]

如:

# 查看分支列表 ~/Repository/MyFirstProject$ git branch -l MyFirstProject01 MyFirstProject02 * MyFirstProject03 MyFirstProject04 master # 删除MyFirstProject04分支 ~/Repository/MyFirstProject$ git branch -d MyFirstProject04 Deleted branch MyFirstProject04 (was 287c845). # 查看分支列表 ~/Repository/MyFirstProject$ git branch -l MyFirstProject01 MyFirstProject02 * MyFirstProject03 master

更改变化

浏览和检查当前分支的文件更改情况。

列出当前分支的版本历史记录 $ git log

如:

# 切换到分支MyFirstProject01 ~/Repository/MyFirstProject$ git checkout MyFirstProject01 Switched to branch 'MyFirstProject01' # 查看MyFirstProject01的版本历史记录 # 下面第一行(HEAD -> MyFirstProject01, MyFirstProject02)的意思是,当前分支是MyFirstProject01,所以头指针指向它,MyFirstProject02则与MyFirstProject01是完全一样一样的,都没有增量修改发生。 ~/Repository/MyFirstProject$ git log commit b6458989f39d267a4670f7d35bc863343fa3fc4d (HEAD -> MyFirstProject01, MyFirstProject02) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:30:26 2019 +0800 init readme.txt commit 287c8454db0ddfacbb5c994dc9999c4f496602a4 (master) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:14:51 2019 +0800 init kyun@kyun-HP-348-G3:~/Repository/MyFirstProject$ echo "Hello World" > Hello.txt kyun@kyun-HP-348-G3:~/Repository/MyFirstProject$ ls app gradle gradlew Hello.txt MyFirstProject.iml settings.gradle build.gradle gradle.properties gradlew.bat local.properties readme.txt # 在分支MyFirstProject01做增量修改,添加一个Hello.txt文件 ~/Repository/MyFirstProject$ git add Hello.txt ~/Repository/MyFirstProject$ git commit Hello.txt -m "init Hello.txt" [MyFirstProject01 2e334d3] init Hello.txt 1 file changed, 1 insertion(+) create mode 100644 Hello.txt # 做了增量后 ~/Repository/MyFirstProject$ git log commit 2e334d333de9acabd86daaa2f8c3c330aeb77007 (HEAD -> MyFirstProject01) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 11:08:20 2019 +0800 init Hello.txt commit b6458989f39d267a4670f7d35bc863343fa3fc4d (MyFirstProject02) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:30:26 2019 +0800 init readme.txt commit 287c8454db0ddfacbb5c994dc9999c4f496602a4 (master) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:14:51 2019 +0800 init 列出文件的修改历史记录,包括修改文件名 $ git log --follow [file] # 切换到分支MyFirstProject01 ~/Repository/MyFirstProject$ git checkout MyFirstProject01 Switched to branch 'MyFirstProject01' ~/Repository/MyFirstProject$ ls app gradle gradlew Hello.txt local.properties readme.txt build.gradle gradle.properties gradlew.bat MyFirstProject.iml settings.gradle # 修改文件名,要用git mv修改,否则修改不了仓库里的文件,当再次签出时,还是会被还原的。 ~/Repository/MyFirstProject$ git mv Hello.txt Hi.txt ~/Repository/MyFirstProject$ git commit -m "rename" [MyFirstProject01 1463e72] rename 1 file changed, 1 deletion(-) delete mode 100644 Hello.txt ~/Repository/MyFirstProject$ git checkout MyFirstProject02 Switched to branch 'MyFirstProject02' ~/Repository/MyFirstProject$ git checkout MyFirstProject01 Switched to branch 'MyFirstProject01' ~/Repository/MyFirstProject$ ls app gradle gradlew Hi.txt MyFirstProject.iml settings.gradle build.gradle gradle.properties gradlew.bat local.properties readme.txt # 列出Hi.txt文件的修改历史记录 ~/Repository/MyFirstProject$ git log --follow Hi.txt commit d9cca2aba6166a4bddc2b33ec74d3f1e1b0b8d21 (HEAD -> MyFirstProject01) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 11:23:47 2019 +0800 rename file name commit 2e334d333de9acabd86daaa2f8c3c330aeb77007 (MyFirstProject05) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 11:08:20 2019 +0800 init Hello.txt 对比不同分支之间的区别 # 对比second-branch与first-branch的区别。 $ git diff [first-branch]...[second-branch]

如:

~/Repository/MyFirstProject$ git diff master MyFirstProject01 diff --git a/Hi.txt b/Hi.txt new file mode 100644 index 0000000..557db03 --- /dev/null +++ b/Hi.txt @@ -0,0 +1 @@ +Hello World diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..372ed7e --- /dev/null +++ b/readme.txt @@ -0,0 +1 @@ +Hello MyFirstProject02

git diff 还可以查看存储区域中有什么。当我们修改了文件或目录,新增了文件或目录,这些变化需要通过git add保存到staged area,即保存区域。以便稍后进行git commit 提交到仓库中。如果你想知道保存区域里有什么,可以使用以下命令:

~/Repository/MyFirstProject$ git diff --staged 显示指定提交的内容变化和输出元数据 每一次commit都会用SHA1生成一个哈希值与之对应 $ git show [commit]

没有指定[commit]的值,则显示最后一次提交的信息,如:

~/Repository/MyFirstProject$ git show commit a25881bc458c6cb415b656090161982730f3d1fc (HEAD -> MyFirstProject01) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 14:46:47 2019 +0800 add a new file diff --git a/Bye.txt b/Bye.txt new file mode 100644 index 0000000..e69de29

指定[commit]的值,则显示指定的commit的内容,如:

# 显示日志 ~/Repository/MyFirstProject$ git log commit a25881bc458c6cb415b656090161982730f3d1fc (HEAD -> MyFirstProject01) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 14:46:47 2019 +0800 add a new file commit 1463e72c63ec1edc591b2aa7011d58224418d2c1 Author: wongkyunban <wongkyunban> Date: Mon Nov 4 14:23:28 2019 +0800 rename commit d9cca2aba6166a4bddc2b33ec74d3f1e1b0b8d21 Author: wongkyunban <wongkyunban> Date: Mon Nov 4 11:23:47 2019 +0800 rename file name commit 2e334d333de9acabd86daaa2f8c3c330aeb77007 (MyFirstProject05) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 11:08:20 2019 +0800 init Hello.txt commit b6458989f39d267a4670f7d35bc863343fa3fc4d (MyFirstProject02) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:30:26 2019 +0800 init readme.txt commit 287c8454db0ddfacbb5c994dc9999c4f496602a4 (master, MyProject02, MyProject01) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:14:51 2019 +0800 init [3]+ Stopped git log # 显示哈希值为b6458989f39d267a4670f7d35bc863343fa3fc4d的commit ~/Repository/MyFirstProject$ git show b6458989f39d267a4670f7d35bc863343fa3fc4d commit b6458989f39d267a4670f7d35bc863343fa3fc4d (MyFirstProject02) Author: wongkyunban <wongkyunban> Date: Mon Nov 4 09:30:26 2019 +0800 init readme.txt diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..372ed7e --- /dev/null +++ b/readme.txt @@ -0,0 +1 @@ +Hello MyFirstProject02 kyun@kyun-HP-348-G3:~/Repository/MyFirstProject$ 添加文件到版本管理器中,使其变化能被追踪到。 $ git add [file]

例子请参考前文。这个操作会将修改缓存到保存区域(stage area),以便稍后,通过git commit一次性将它们提交,如果要把它们从保存区域撤出,可以通过以下命令进行:

$ git reset HEAD [file] 提交 $ git commit -m "[descriptive message]"

例子请参考前文

重做

撤消[commit]之后的所有提交,所有修改会在本地被保留,只是撤销了提交到远程仓库 $ git reset [commit] 放弃所有历史记录和对指定提交的更改 git reset --hard [commit]

同步本地仓库与GitHub上的远程仓库

从远程分支下载所有历史记录 $ git fetch 合并远程跟踪分支到本地当前分支 $ git merge 上传本地所有分支的提交到GitHub $ git push 用远程对应分支的所有新的提交更新当前本地工作分支,git pull集合了git fetch和git merge 功能。 $ git pull

.gitgnore文件的作用

每个使用Git管理的项目都有一个叫.gitgnore的隐藏文件,它的作用是忽略指定的文件,这样Git就不会去跟踪这些文件的修改,它们也不会被提交到版本库。典型的android studio IDE的android项目的.gitgnore配置:

# Built application files *.apk *.ap_ *.aab # Files for the ART/Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ out/ # Uncomment the following line in case you need and you don't have the release build type files in your app # release/ # Gradle files .gradle/ build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # IntelliJ *.iml .idea/workspace.xml .idea/tasks.xml .idea/gradle.xml .idea/assetWizardSettings.xml .idea/dictionaries .idea/libraries # Android Studio 3 in .gitignore file. .idea/caches .idea/modules.xml # Comment next line if keeping position of elements in Navigation Editor is relevant for you .idea/navEditor.xml # Keystore files # Uncomment the following lines if you do not want to check your keystore files in. #*.jks #*.keystore # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild # Google Services (e.g. APIs or Firebase) # google-services.json # Freeline freeline.py freeline/ freeline_project_description.json # fastlane fastlane/report.xml fastlane/Preview.html fastlane/screenshots fastlane/test_output fastlane/readme.md # Version control vcs.xml # lint lint/intermediates/ lint/generated/ lint/outputs/ lint/tmp/ # lint/reports/

更多信息请参考《.git目录里的目录的作用》

最后来一表对git命令进行总结:

命令描述创建一个仓库或叫创建一个工作区域git clone克隆一个仓库到目录下git init创建一个空的Git仓库或重新初始化一个已存在的仓库作用于当前分支的更改的git add添加文件内容到索引git mv移动或重命名文件、目录git reset重置当前头指针到指定的状态git rm从工作目录树和索引中移除文件历史记录git bisect使用二进制搜索查找引入错误的提交git grep打印匹配的行git log显示提交日志git show显示多种对象类型git status显示工作树的状态标记、调整git branch列出、创建、删除分支git checkout切换分支或恢复工作树文件git commit记录变化git diff显示提交之间或工作树之间的改变git merge合并git tag创建、列出、删除或验证一个用GPG签名的标签对象远程仓库操作git fetch获取所有远程仓库的历史记录git pull从远程仓库拉取到本地git push向远程仓库提交

谢谢阅读

最新回复(0)