参考
- https://www.runoob.com/manual/git-guide/
- https://github.com/rogerdudler/git-guide
- https://docs.github.com/cn/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh
- 零声学院
创建仓库
git init --bare xx.git #裸仓库, 远端仓库以git结尾, 也可以不用
git init xx.git #一般仓库
配置文件
git config --global user.name "xxx"
git config --global user.email "xxx@xx.com"
git config user.name "xxx"
git config user.email "xxx@xx.com"
克隆仓库
git clone username@host:/path/to/repository #用绝对地址
裸仓库与一般仓库有什么不同
git init --bare bare_repo.git
git init repo.git
在客户端分别clone,并添加文件,并提交
git clone test@192.168.31.3:/home/test/bare_repo.git #裸仓库
#warning: You appear to have cloned an empty repository.
git clone test@192.168.31.3:/home/test/repo.git #一般仓库
#warning: You appear to have cloned an empty repository.
cd bare_repo
git config user.name "hello"
git config user.email "hello@world.com"
echo "helloworld" > helloworld
git add .
git commit -m "first commit"
git push origin master
#远程仓库能看到提交,但是没有文件,实际文件已压缩包形式保存在object中
#This operation must be run in a work tree
cd repo
git config user.name "hello"
git config user.email "hello@world.com"
echo "helloworld" > helloworld
git add .
git commit -m "first commit"
git push origin master #会出错,错误信息看下面
#远程仓库能看到提交,文件在暂存区,需要手动
#git checkout -f
主要区别是,裸仓库不包含仓库区,不能在这个目录下执行一般使用的 Git 命令。
裸仓库和一般仓库都可以clone,但是push的时候,一般仓库会拦截,需要修改配置文件。
这样的设计是避免这样的情况,一般仓库作为远程仓库,但是本地和远程仓库都有人在修改,然后本地仓库push到远程仓库,会造成混乱。
远程仓库初始化用裸仓库。
https://zhuanlan.zhihu.com/p/24151683
https://stackoverflow.com/questions/7861184/what-is-the-difference-between-git-init-and-git-init-bare
错误提示
bash: git-upload-pack: command not found
bash: git-receive-pack: command not found
原因是因为git是自定义安装在/usr/local下的
解决方法
- 将git-upload-pack添加软连接到/usr/bin/git-upload-pack下
- git clone test@192.168.31.3:/home/test/bare_repo.git -u “/usr/local/git/bin/git-upload-pack”
- git push origin master --receive-pack=/usr/local/git/bin/git-receive-pack
- git pull origin master --upload-pack “/usr/local/git/bin/git-upload-pack”
https://stackoverflow.com/questions/56990207/fatal-bad-config-value-for-receive-denycurrentbranch-in-config?noredirect=1
错误提示
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To 192.168.31.3:/home/test/repo.git
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to '192.168.31.3:/home/test/repo.git'
原因是远程仓库初始化为一般仓库了。
解决方法
在远程仓库的.git/config中配置文件
[receive]
denyCurrentBranch = ignore
添加文件追踪
git add <filename>
git add .
git add *
提交
git commit -m "xxx"
查看信息
git diff
git log
git log --graph
git status
分支
git checkout <branch name> #切换分支
git checkout -b <branch name> #新建并切换分支
git branch -a #查看所有分支
git branch -d <branch name> #删除分支
git branch -m <branch name> #分支改名
远端仓库
git remote add <name> <url> #新增远端仓库地址
git remote -v #列出远端仓库地址
git remote rm <name>
提交到远端仓库
git push <远程主机名> <本地分支名>
git push <远程主机名> <本地分支名>:<远程分支名>
将远端仓库更新到本地
git fetch <远程主机名> <分支名>
合并当前分支
git merge <分支名>
pull=fetch+merge
rebase
场景1:冲突
两个本地仓库链接同一个远程仓库,分别进行修改并提交(注意不同的名字和邮件)
git config user.name xxx
git config user.email xxx
A修改并提交,B修改再提交,结果如下
git push origin master
test@192.168.31.3's password:
To 192.168.31.3:/home/test/repo.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to '192.168.31.3:/home/test/repo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
按照提示用pull
git pull origin master
test@192.168.31.3's password:
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 244 bytes | 15.00 KiB/s, done.
From 192.168.31.3:/home/test/repo
* branch master -> FETCH_HEAD
6ca04f8..dce888f master -> origin/master
Auto-merging main.c
CONFLICT (content): Merge conflict in main.c
Automatic merge failed; fix conflicts and then commit the result.
手动修改冲突
#include <stdio.h>
int add(int a,int b){
return a+b;
}
<<<<<<< HEAD
int mul(int a,int b){
return a*b;
=======
int sub(int a,int b){
return a-b;
>>>>>>> dce888f5711eacdf026accb3693cb24c0c98fe88
}
int main(){
return 0;
}
B修改冲突,add,commit,push
A则pull
场景2:rebase,合并多次提交
A进行3次提交到本地仓库,如下
git log --graph --pretty=oneline --abbrev-commit
* 14820ae (HEAD -> master) five commit
* 112f8ea four commit
* 1de36af third commit
* 190cc65 (origin/master) second commit
* 105045c second commit
|\
| * dce888f second commit
* | 2aff90c second commit
|/
* 6ca04f8 first
git rebase -i HEAD~n #i进入交互式,n指几次commit
# 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.
#
场景3:bisect, 定位某个出错的提交
场景4:配置ssh key,免密登录GitHub
- 生成ssh key
ssh-keygen - 登陆github,添加公钥
- 测试是否添加成功
ssh -i .ssh/id_rsa_github -T git@github.com - 修改配置文件.ssh/config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github