git pro tips - RLidea/dev.docs GitHub Wiki

Git Notes for Professionals์—๋„ ํŒ์ด ๋งŽ์œผ๋‹ˆ ์ฐธ๊ณ .

๋งค๋ฒˆ push/pull ํ•  ๋•Œ๋งˆ๋‹ค ๊ณ„์ • ์ •๋ณด ์ž…๋ ฅํ•˜๊ธฐ ๊ท€์ฐฎ๋‹ค

git config credential.helper store

ref: How can I perform a git pull without re-entering my SSH password?

ํ˜„์žฌ ์ž‘์—…๋ฌผ์„ ๋‹ค๋ฅธ ๋ธŒ๋Ÿฐ์น˜์— ์ปค๋ฐ‹ํ•˜๊ธฐ

git stash
git checkout other-branch (๋ธŒ๋Ÿฐ์น˜๋ฅผ ์ƒ์„ฑํ•ด์•ผํ•˜๋ฉด git checkout -b other-branch)
git stash pop

Private repo ๋ฅผ ์„œ๋ฒ„์— clone ํ•˜๊ธฐ

$ ssh-keygen

์œผ๋กœ rsa ํ‚ค๋ฅผ ์ƒ์„ฑํ•œ ๋’ค(์ฐธ๊ณ ), public ํ‚ค๋ฅผ github > settings > SSH keys ์— ๋“ฑ๋กํ•ด์ค€๋‹ค.

๋‹ค๋ฅธ ๋ฐฉ๋ฒ•: ์ฐธ๊ณ  ๋งํฌ

๊ฐ€์žฅ ์ตœ์‹  commit์˜ author ์ˆ˜์ •ํ•˜๊ธฐ

โˆ™ ์ฃผ์˜์‚ฌํ•ญ

commit์„ ์ˆ˜์ •ํ•˜๋ฉด ํ•ด๋‹น commit์˜ key ๊ฐ’์ด ๋ณ€๊ฒฝ๋œ๋‹ค. history๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฏ€๋กœ remote์— pushํ•˜๋ ค๋ฉด $ git push --force ํ˜น์€ $ git push --force-with-lease๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๊ณต๋™์ž‘์—…์ž๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๊ธฐ์กด ์ž‘์—…๋ฌผ์„ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ cloneํ•ด์•ผ ํ•˜๋Š” ๋“ฑ์˜ ์—ฌ๋Ÿฌ ๋ถˆํŽธํ•จ์ด ์ƒ๊ธฐ๋ฏ€๋กœ commit์˜ ๋ณ€๊ฒฝ์€ ๋˜๋„๋ก์ด๋ฉด ํ•˜์ง€ ์•Š๋Š” ํŽธ์ด ์ข‹๋‹ค.

โˆ™ ๋ฐฉ๋ฒ•

$ git commit --amend --author="username <[email protected]>"

์ด ๋•Œ ์ด๋ฉ”์ผ์„ < >๋กœ ๊ฐ์‹ธ์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๊ฐ€ ๋œฌ๋‹ค.

fatal: --author 'username [email protected]' is not 'Name <email>' and matches no existing author

--amend ๋ช…๋ น์–ด๊ฐ€ ์‹คํ–‰๋˜๋ฉด commit ๋ฉ”์„ธ์ง€๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์ด ํ‘œ์‹œ๋œ๋‹ค. :wq๋กœ ์ €์žฅ ํ›„ ์ข…๋ฃŒํ•˜๋ฉด commit์˜ author์™€ ๋ฉ”์„ธ์ง€๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฐธ๊ณ : author ์™€ committer๋ฅผ ๋ชจ๋‘ ๋ฐ”๊พธ๋ ค๋ฉด

$ git log --pretty='[%cn]%ce: %cd' // commiter ํ™•์ธ (cn: committer name, ce: committer email, cd: commit date)
$ git -c user.name="username" -c [email protected] commit --amend --reset-author

ํŠน์ • commit์˜ author ์ˆ˜์ •ํ•˜๊ธฐ

rebase๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. A -> B -> C -> D(Head) ์ˆœ์„œ๋กœ commit์ด ์ž‘์„ฑ๋˜์–ด ์žˆ์„ ๋•Œ, C commit์˜ author๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด A ํ˜น์€ B commit์˜ key๋ฅผ ์•Œ์•„์•ผํ•œ๋‹ค. ์ฆ‰ ์ˆ˜์ •ํ•˜๋ ค๋Š” commit๋ณด๋‹ค ์ด์ „์— ์ž‘์„ฑ๋œ commit์„ base๋กœ ๋‹ค์‹œ(re) ์„ค์ •, rebase ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

โˆ™ ์ฃผ์˜์‚ฌํ•ญ

rebase๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ์ˆ˜์ •ํ•œ commit ์ดํ›„์˜ ๋ชจ๋“  commit๋“ค์˜ key ๊ฐ’ ๋˜ํ•œ ๋ณ€๊ฒฝ๋œ๋‹ค. history๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ฏ€๋กœ remote์— pushํ•˜๋ ค๋ฉด $ git push --force ํ˜น์€ $ git push --force-with-lease๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๊ณต๋™์ž‘์—…์ž๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๊ธฐ์กด ์ž‘์—…๋ฌผ์„ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ cloneํ•ด์•ผ ํ•˜๋Š” ๋“ฑ์˜ ์—ฌ๋Ÿฌ ๋ถˆํŽธํ•จ์ด ์ƒ๊ธฐ๋ฏ€๋กœ commit์˜ ๋ณ€๊ฒฝ์€ ๋˜๋„๋ก์ด๋ฉด ํ•˜์ง€ ์•Š๋Š” ํŽธ์ด ์ข‹๋‹ค.

โˆ™ ๋ฐฉ๋ฒ•

$ git log // ๋ฐ”๊พธ๋ ค๋Š” commit ์ด์ „์— ์ž‘์„ฑ๋œ commit์˜ key๋ฅผ ํ™•์ธ
$ git rebase --interactive [key] // git rebase -i [key]๋„ ๊ฐ€๋Šฅ

rebase ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด key๋กœ ์‚ฌ์šฉํ•œ commit ์ดํ›„์˜ ๋ชจ๋“  commit(merge commit ์ œ์™ธ)๋“ค์ด ์ฐจ๋ก€๋กœ ํ‘œ์‹œ๋œ๋‹ค. ๊ทธ ์ค‘ ์ˆ˜์ •์„ ์›ํ•˜๋Š” commit์˜ pick์„ edit์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

edit 6ca128b commit message1
pick 210dd87 commit message2
pick 730fcc1 commit message3
edit 9de4e16 commit message4

...

:wq๋กœ ์ €์žฅ ํ›„ ์ข…๋ฃŒํ•˜๊ณ  ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ํ•ด๋‹น commit์˜ author๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.

$ git commit --amend --author="username <[email protected]>"

์ด ๋•Œ ์ด๋ฉ”์ผ์„ < >๋กœ ๊ฐ์‹ธ์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๊ฐ€ ๋œฌ๋‹ค.

fatal: --author 'username [email protected]' is not 'Name <email>' and matches no existing author

--amend ๋ช…๋ น์–ด๊ฐ€ ์‹คํ–‰๋˜๋ฉด commit ๋ฉ”์„ธ์ง€๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์ด ํ‘œ์‹œ๋œ๋‹ค. :wq๋กœ ์ €์žฅ ํ›„ ์ข…๋ฃŒํ•˜๋ฉด commit์˜ author์™€ ๋ฉ”์„ธ์ง€๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

$ git rebase --continue

์ดํ›„ --continue ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด edit์œผ๋กœ ์„ค์ •ํ•œ ๋‹ค์Œ commit์œผ๋กœ ์ด๋™ํ•˜๊ณ , ์œ„์™€ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ author๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค. ๋ชจ๋“  ๋ณ€๊ฒฝ์„ ๋๋งˆ์นœ ๋’ค --continue ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด rebase๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค.

์ฐธ๊ณ : initial commit์˜ author๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด

$ git rebase --interactive --root

์ฐธ๊ณ : rebase ์‚ฌ์šฉ ์‹œ merge commit์„ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด

$ git rebase --interactive --rebase-merges [key]

์ฐธ๊ณ : author ์™€ committer๋ฅผ ๋ชจ๋‘ ๋ฐ”๊พธ๋ ค๋ฉด

$ git log --pretty='[%cn]%ce: %cd' // commiter ํ™•์ธ (cn: committer name, ce: committer email, cd: commit date)
$ git -c user.name="username" -c [email protected] commit --amend --reset-author

๋ชจ๋“  commit์˜ author์™€ committer ๋ณ€๊ฒฝํ•˜๊ธฐ

shell script ๋กœ ํ•ด๊ฒฐํ•˜์ž. ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— ch.sh๋ผ๊ณ  ํŒŒ์ผ์„ ๋งŒ๋“ค๊ฒ ๋‹ค.

#!/bin/sh
git filter-branch -f --env-filter '

OLD_EMAIL="your@old_email.com"
CORRECT_NAME="your name"
CORRECT_EMAIL="your@new_email.com"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

์‹คํ–‰์€

$ chomod +x ch.sh
$ ./ch.sh

or

$ sh ./ch.sh 

๋ชจ๋“  commit์˜ author์™€ committer๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  backup repo์— ํ‘ธ์‹œ๊นŒ์ง€ ํ•˜์ž

remote backup repo ๋Š” ๋ฏธ๋ฆฌ ๋“ฑ๋กํ•œ ๋’ค ์‹คํ–‰ํ•  ๊ฒƒ.

#!/bin/sh
git branch backup
git checkout backup
git filter-branch -f --env-filter '

OLD_EMAIL="[email protected]"
CORRECT_NAME="your name"
CORRECT_EMAIL="[email protected]"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

git push -f backup backup:master
git checkout master
git branch -D backup

์ œ์™ธํ•˜๊ณ  ์‹ถ์€ ํŒŒ์ผ์ด ์žˆ๋Š”๋ฐ .gitignore๋ฅผ ๊ฑด๋“œ๋ฆฌ๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด?

.git/info/excludeํŒŒ์ผ์„ ์ˆ˜์ •ํ•œ๋‹ค. ์ž‘์„ฑ ๋ฐฉ๋ฒ•์€ .gitignore ์™€ ๊ฐ™๋‹ค.

example:

# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
exclude-file-name

์ฐธ๊ณ 

ํ˜„์žฌ ์‹œ์  ์ดํ›„์˜ ํŠน์ • ํŒŒ์ผ ๋ณ€๊ฒฝ์‚ฌํ•ญ๋“ค์„ ํŒŒ์ผ์„ ์ œ๊ฑฐํ•˜์ง€ ์•Š๊ณ  ignore ์ฒ˜๋ฆฌํ•˜๊ธฐ

git update-index --assume-unchanged <ํŒŒ์ผ ๊ฒฝ๋กœ>

์—ฌ๋Ÿฌ git user ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ์–ด์ธํ•œ ๋ฐฉ๋ฒ•

1. ๊ฐ ์œ ์ €๋‹น ssh key ์ƒ์„ฑ

$ ssh-keygen -t rsa -b 4096 -C "[email protected]"

ํŒŒ์ผ๋ช…์€ ๋ฌด์—‡์œผ๋กœ ํ•ด๋„ ๋˜์ง€๋งŒ ๊ฐ ๊ณ„์ •๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ํ•ด์ค˜์•ผ ํ•œ๋‹ค. ํŽธ์˜์ƒ id_rsa_work๋“ฑ์œผ๋กœ ์•Œ์•„๋ณด๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์ž. ์ƒ์„ฑํ•œ ํ‚ค์˜ ๊ถŒํ•œ์€ 600์œผ๋กœ ์ ์šฉํ•ด์ค€๋‹ค.

chmod 600 id_rsa_yourid
chmod 600 id_rsa_yourid.pub

2. ssh public key ๋ฅผ ๊ฐ๊ฐ์˜ github ๊ณ„์ •์— ๋“ฑ๋ก (๊ณต์‹๋ฌธ์„œ)

๊ฐ๊ฐ์˜ ๊ณ„์ •์—์„œ SSH and GPG Keys๋ฉ”๋‰ด์— ssh public key๋ฅผ ๋“ฑ๋กํ•œ๋‹ค

pbcopy < id_rsa_work.pub

3. ssh config ์„ค์ •

~/.ssh/configํŒŒ์ผ์— (์—†์œผ๋ฉด ์ƒ์„ฑํ•ด์„œ) ์ž์‹ ์˜ ๊ณ„์ •์„ ๋“ฑ๋กํ•ด์ค€๋‹ค.

# Personal git
Host github.com-personal
	HostName github.com
	User git
	IdentityFile ~/.ssh/id_rsa_personal


# Work git
Host github.com-work
	HostName github.com
	User git
	IdentityFile ~/.ssh/id_rsa_work

๊ทธ๋ฆฌ๊ณ  ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ

๋ฆฌํ„ด์œผ๋กœ ์ž์‹ ์˜ ์•„์ด๋””๊ฐ€ ๋‚˜์˜จ๋‹ค๋ฉด ์„ฑ๊ณต์ด๋‹ค.

4. ์„ค์ • ํŒŒ์ผ ์ƒ์„ฑ

~/Workspace/Company ๋””๋ž™ํ† ๋ฆฌ ์•ˆ์—์„œ๋Š” ๋‹ค๋ฅธ .gitconfig ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์ œ์ด๋‹ค. vi ~/.gitconfig

[user]
    name = Your Name
    email = [email protected]

[includeIf "gitdir:~/Workspace/Company/"]
    path = ~/Workspace/Company/.gitconfig

vi ~/Workspace/Company/.gitconfig

[user]
    email = [email protected]

5. git clone

์ด์ œ ํ•„์š”ํ•œ repo ๋ฅผ ํด๋ก ํ•˜์ž. ์ด๋•Œ SSH๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, origin url ์ด ๋‹ค๋ฆ„์— ์œ ์˜ํ•œ๋‹ค. example:

git clone [email protected]:myCompany/myProject.git

๊ธฐํƒ€. ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ๊นƒ ์œ ์ € ๋ณ€๊ฒฝํ•˜๊ธฐ

๊ธฐ๋ณธ์ ์œผ๋กœ ๊นƒ ์œ ์ €์˜ ์ •๋ณด๋Š” ์•„๋ž˜ ๋ช…๋ น์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

git config user.email <your-email>
git config user.name <your-name>

ํ•˜์ง€๋งŒ git-user-switch ๋ฅผ ์ด์šฉํ•˜๋ฉด ํŽธ๋ฆฌํ•˜๋‹ค.

npm i -g git-user-switch

ํŠน์ • branch ๋งŒ pull ํ•ด์˜ค๊ธฐ

ํ˜„์žฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” branch ๋กœ remote branch ๋ฅผ pull ํ•ด์˜จ๋‹ค.

remote ์— ์–ด๋–ค ๋ธŒ๋Ÿฐ์น˜๋“ค์ด ์žˆ๋Š”์ง€ ํ™•์ธ

git remote show origin

ํ˜„์žฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” branch ํ™•์ธ

git branch -v

์›ํ•œ๋‹ค๋ฉด ๋ธŒ๋Ÿฐ์น˜๋ฅผ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ์ƒ์„ฑํ•œ๋‹ค

git checkout target-branch
git checkout -b target-branch

๊ทธ๋ฆฌ๊ณ  pull

git pull origin <branch name> 
โš ๏ธ **GitHub.com Fallback** โš ๏ธ