사용자 도구

사이트 도구


git:cheatsheet

Git Cheatsheet

  • git Cheat Sheet
  • git clone [저장소주소] [디렉토리명] : “디렉토리명”으로 저장소 복제
  • git clone --depth 1 [저장소주소] [디렉토리명] : “디렉토리명”으로 저장소를 복제하는데, 히스토리는 복제하지 않는다(빠르다).
  • git clone --branch <branchname/tagname> [저장소주소] : 특정 branch/tag 를 클론한다.

설정 보기

git config --list --local # 현재 저장소 설정
git config --list --global # 공통 설정

올리기

  • git add 파일 : 저장소에 추가
  • git commit -m “메시지” : 로컬 커밋
  • git push [origin] : 원격 저장소 origin으로 Push

commit template

  • 기본적으로 commit.template 설정에 있는 파일을 템플릿으로 사용한다.
  • git commit -t <file>/git commit –template=<file> 로 명시적 지정도 된다.
  • # 는 주석이다.

받기

  • git fetch : 원격 저장소 origin에서 받아오기. Merge는 안함.
  • git pull : 원격 저장소 origin에서 최신 데이터를 가져와 Merge까지 하기
  • hitory 없이 최소한으로 clone 하고 .git 디렉토리 삭제하기
    git clone --depth=1 git://someserver/somerepo dirformynewrepo
    rm -rf !$/.git # !$ 는 직전 명령의 마지막 인자(dirformynewrepo) 를 뜻한다.

비교

  • git status : 워킹 디렉토리 상태 보기
  • git diff 커밋ID_1 커밋ID_2 [파일명] : 두 커밋로그 사이의 차이점 비교. 파일명을 지정하면 두 커밋간 해당 파일의 차이점 비교
  • git diff HEAD^ [파일명] : 직전 커밋과의 비교
  • git diff HEAD^ HEAD^^ [파일명] : 직전과 그 직전 커밋과의 비교
  • git blame 파일 : 파일을 누가 언제 고쳤는지 보여줌.
  • git diff 브랜치1..브랜치2 : 두 브랜치간의 비교
  • git diff 다른브랜치 -- 파일 : “파일”의 현재 브랜치와 다른 브랜치간의 차이점을 보여준다.
  • git diff --name-status 브랜치1..브랜치2 : 두 브랜치간의 변경된 파일 목록과 상태. --name-only 옵션은 파일 이름만 출력.
  • git diff --stat --color 브랜치1..브랜치2 : 두 브랜치간의 차이를 컬러 차트로 보여줌.
  • git diff --name-only [COMMIT1] [COMMIT2] : 두 커밋간의 변경된 파일 목록
  • git diff --name-only HEAD~10 HEAD~5 : 헤드에서 10번째 커밋과 헤드에서 5번째 커밋간의 변경된 파일 목록
  • git diff --staged : 이미 commit 된 것과 staged 된 파일의 변경 비교
  • git log branchA..branchB : 두 브랜치간의 commit 목록 diff.
    • git log 더적은쪽브랜치..더큰브랜치 : 두 브랜치가 포함관계일 때 더적은쪽을 왼쪽에 둬야했음.
    • git log --oneline --no-merges --no-decorate branchA..BranchB : 두 브랜치간의 commit 목록 diff 인데 머지 커밋은 제외
    • git log --graph --left-right --cherry-pick --oneline 브랜치1...브랜치2 : 브랜치간 빠진 커밋 찾기 diff 와 같은듯. cherry-pick 으로 이 브랜치 저 브랜치 머지하다가 누락된곳 찾기?
    • 차이나는 Jira 이슈 번호만 뽑기
      git log --oneline --no-merges --no-decorate 브랜치1..브랜치2 \
          | grep -o "[A-Z]\{6\}-[0-9]\{4\}" | sort | uniq

파일 보기 view / show

  • git show [커밋ID]:/path/to/file : 특정 커밋에서의 파일의 내용을 보여줌

Log

  • git log [파일] : 특정 파일 혹은 워킹 디렉토리에 대한 커밋 로그를 보여줌
    • git log -숫자 : 최근 숫자 갯수만큼의 로그만 보여줌
  • git log --full-history [파일] : 사라진 커밋 히스토리까지 다 보여준다.
  • git log --author="Jon" : 특정 사용자로 커밋 로그 검색
  • git log --grep=“정규표현식” : 정규표현식을 만족하는 커밋 메시지가 있는 로그를 보여줌
    • --all-match : 모든 --grep 옵션을 다 만족시키는 것만 검색.

사라지는 Commit

가끔씩 Commit이 사라지고 git log --full-history [파일] 명령으로 로그를 봐야 커밋 히스토리가 보이는 경우가 발생한다. 이는 브랜치 Merge 시에 다른 사람의 작업(없어진 커밋)과 충돌이 났을 때 IntelliJ로 치면 Accept yours 혹은 Accept theirs 처럼 특정 작업을 모두 무시하는 Merge를 수행했을 때 발생한다.

특정 커밋으로 소스 전체 변경

  • git checkout [커밋ID] : 특정 커밋 시점으로 모든 소스를 변경한다.
  • git checkout HEAD~1 : 한 단계 전으로 이동
  • git checkout HEAD~10 : 10 단계 전으로 이동
  • git checkout master : 다시 master 브랜치로 원상 복구

삭제

  • git rm 파일 : 특정 파일삭제.

이름 변경(rename)

커밋로그 일괄 변경하기

  • Push 하기 전의 여러 commit들의 커밋 로그 변경하기
  • $parent_of_flawed_commit에 대해 rebase
    git rebase --interactive $parent_of_flawed_commit
    • 편집기가 뜨면 커밋로그를 변경하고자 하는 것에 대해
    • pickreword 로 변경하고 저장
    • 이제 하나씩 에디터가 뜨면 커밋 로그를 변경
    • 자동으로 다시 커밋까지 해줌.
    • --interactive == -i

커밋로그의 Author 일괄 변경하기

  • 여러개의 커밋에 대한 변경
    # 특정 commit 지정할 경우
    git rebase -i -p 원하는커밋바로앞커밋hash ## 바로 앞!!! ##
     
    # 특정 갯수 지정할 경우
    git rebase -i HEAD~갯수
    # Push 안된 모든 커밋을 지정할 경우
    git rebase -i $parent_of_flawed_commit
    # 여기서 나온 편집기 화면에서 고치고자 하는 커밋을 pick 대신 edit로 수정한다.
    # ------------------------------
    # 이제 작성자 변경작업
    git commit --amend --author "New Author Name <email@address.com>" 
    git rebase --continue
     
    # 이미 push 된 상황이면 --force 로 push 해야만 함.
    git push --force
  • 가장 최근 한 개만 변경
     git commit --amend --author "New Author Name <email@address.com>"

커밋로그 합치기

  • 아직 푸시 전이라면 커밋로그를 합쳐서 푸시하는 것이 더 좋을 때가 있다.
  • 커밋 로그 Author 변경과 거의 동일하지만 squash를 사용한다는 점이 다르다.
    # 특정 갯수를 지정할 경우
    git rebase -i HEAD~갯수
    # 맨 처음 커밋로그(합쳐진 결과가 될 커밋)을 제외하고 "squash"로 변경하고 저장.
  • 절대 이미 push 해버린 커밋들을 합치지 말 것.

마지막 커밋에 신규 변경사항 추가로 넣기 (Push 전)

# 변경을 추가하고
git add changelog.md
# 마지막 커밋에 넣는다. commit message를 신규로 작성해야 한다.
git commit --amend
 
# commit message는 그대로 두고 싶다면
git commit --amend --no-edit

변경 파일 취소 (Revert)

  • git fetch origin; git reset --hard origin/<BRANCH> : 커밋을 모두 취소하고 origin/<BRANCH> 상태로 변경
  • push 되지 않은 commit들 취소할 때 커밋되지 않은 변경사항들 유지하기
    # 커밋 외의 변경사항이 있을 때 변경 사항들을 stash 해 두어야 한다.
    git stash
    git reset --hard origin/master # 올바른 리모트 브랜치로 바꿔줄것
    git stash pop
  • git reset --soft HEAD^ : Local 커밋을 취소하지만 커밋으로 인한 변경사항은 유지한다.
  • git checkout -- [파일] : 아직 스테이지로 안 올라간 파일의 변경 취소
  • git reset --hard HEAD : 커밋 되지 않은 모든 변경사항 취소. 최종 커밋한 상태로 돌아감.
  • git reset HEAD [파일] : 스테이지에 올라간 파일을 스테이지에서 뺌(파일 자체는 변경 상태 유지)
  • git rest HEAD^ : push 전에 마지막 커밋을 취소시키되, 변경을 그대로 유지하게 되돌린다.(파일을 빼먹고 커밋했거나 한 경우)
  • git revert [commit_id …] : 특정 커밋의 변경 사항을 되돌리며, 되돌리는 행위 자체를 하나의 새로운 커밋으로 만든다. 실제 기존 커밋 히스토리가 사라지지는 않는다. 이미 Push된 커밋도 가능.
  • Undoing Merges
    git revert -m [parent] [commit_id]
    # example
    git revert -m 1 xxxx
    • Merge를 revert 했다가 다시 merge하고 싶을 때는 Merge에 대한 Revert 커밋을 revert 해야한다.
    • git clean -d -f : 디렉토리까지 삭제
    • 여기에 -x 옵션을 주면 ignore된 파일들까지 모두 삭제
  • upstream 과 동일하게 변경(push 안된 commit 까지 모두 취소)
    # 현재 develop 브랜치일 때
    git fetch origin develop
    git reset --hard origin/develop
    git clean -d --force

신규 프로젝트 올리기

이미 파일이 많은 신규 프로젝트를 Git 리포지토리로 올리는 작업이 필요한 경우. Git – setting up a remote repository and doing an initial push

  1. 먼저 Git 원격 리포지토리를 생성한다.
  2. 로컬에서 프로젝트디렉토리로 이동하여 다음과 같이 명령을 실행한다.
    # 프로젝트 이름과 원격 리포지토리 이름이 my_project 일 때
    cd my_project
    git init
     
    # 불필요한 파일들을 모두 정리한 뒤에
    git add * # 혹은 git add --all
    git commit -m '프로젝트 초기 설정'
    git remote add origin [git_repository]/my_project.git
    git push -u origin master
  3. 커밋이 한 개도 없는 원격 리포지토리에 Push를 최초로 할 때는 git push origin masterorigin master를 명시해줘야 한다.(git 1.8 이상에서는 상관 없는 듯)

Remote URL 변경하기

git remote set-url origin git://new.url.here
# origin을 원하는 remote 저장소 이름으로 변경

Branch

  • git branch -vv : 브랜치의 상세 정보 출력. upstream 까지 보여줌
  • git branch --show-current : 현재 브랜치 이름
  • git branch : 브랜치 정보 출력
  • git branch 이름 : 새 브랜치 만들기
  • git checkout 이름 : 예전 방식
    • local 브랜치가 존재할 경우에는 해당 브랜치를 체크아웃 한다.
    • local 브랜치가 존재하지 않고 remote 에 일치하는 이름의 브랜치가 딱 하나 존재하면 local 브랜치를 생성하고 remote 브랜치를 tracking 한다. 즉, git checkout -b <branch> --track <remote>/<branch> 명령이 자동 실행된다.(--guess옵션 기본적용)
  • git switch 이름 : 해당 브랜치로 스위치. checkout에서 브랜치 관련된 기능만 수행하는 버전.
    • local 브랜치가 존재할 경우 해당 브랜치로 스위치
    • local 브랜치가 존재하지 않고 remote 에 일치하는 이름의 브랜치가 딱 하나 존재하면 local 브랜치를 생성하고 remote 브랜치를 tracking 한다. 즉, git switch -c <branch> --track <remote>/<branch> 로 작동한다.(--guess옵션 기본적용)
  • git switch -c 이름 : 브랜치 생성하고 해당 브랜치로 스위치
    • git checkout -b 이름 : 예전 방식
  • git checkout - : 직전 브랜치 체크아웃
  • git branch -d 이름 : 브랜치 삭제, -D는 강제 삭제
  • git branch --merged : 머지가 완료된 브랜치 목록을 보여준다. master를 제외한 머지 완료된 브랜치는 삭제해 버리자.
  • git branch --no-merged : 머지 안된 브랜치 목록을 보여준다.
  • git branch -v : 각 브랜치의 최종 커밋을 보여준다.
  • git branch -a : 전체 브랜치(리모트 포함) 목록
  • git branch -r : 리모트 브랜치 목록
  • git remote prune origin : 정확한 의미 확인 필요. origin 에 브랜치가 없는데 local 에 연결이 있을 경우 이를 끊어주는 역할인듯. 실제로 local branch 를 삭제하는게 아님.

master to main 변경

아래 명령을 실행하면 master 브랜치의 모든 커밋등이 main으로 넘어간다.
git branch -m master main
 
# 올리기
git push -u origin main
 
# HEAD를 main으로 변경
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
 
# github/gitlab 등에서 기본 브랜치 변경
# master 브랜치 삭제
git push origin --delete master
 
# 확인
git branch -a

Remote Branch

  • 로컬 브랜치를 만들어 작업하고 나서 다음과 같이 작업한다. origin은 원격지 이름으로 대체될 수 있다.
  • git switch -t origin/serverfix : 원격 브랜치를 브랜치이름 그대로 생성하며 체크아웃.
    • git checkout --track origin/serverfix : 옛날방식
  • git switch -c [localbranchname] -t origin/[remotebranchname] : 원격 브랜치를 로컬 브랜치를 생성하며 체크아웃한다. 로컬 브랜치 이름을 다르게 가져갈 수 있다.
    • git checkout -b [localbranchname] origin/[remotebranchname] : 옛날방식
  • git push --set-upstream origin [remotebranchname] : 현재 브랜치를 원격 브랜치에 연결하고 푸시한다.
  • git push origin [remotebranchname] : 원격브랜치로 push. 원격브랜치가 없으면 만든다.
  • git push origin [localbranchname]:[remotebranchname] : 특정 로칼 브랜치를 지정하여 원격브랜치로 푸시. 원격 브랜치가 없으면 만든다.
    • 이 로컬 브랜치에서 push/pull 을 자동으로 지정된 원격 브랜치로 가게 된다.
  • git push origin :[remotebranchname] : 원격 브랜치 삭제. 중간의 콜론(:)이 있다는 점에 주의할 것.
  • git clone -b [remotebranchname] [remote_repo 주소] : 원격 브랜치를 바로 clone 한다.
  • git branch --track [localbranchname] origin/[remotebranchname] : 로컬 브랜치와 리모트 브랜치간의 연결

2개 이상의 Remote 사용

  • Github 등에서 fork를 했을 때 원본 소스와의 동기화등에 필요.
  • git remote add <forkname> <forkgiturl>
  • git fetch <forkname> : 소스 받아오기
  • git merge <forkname>/<branch> : 원본 리포의 특정 브랜치를 내 브랜치에 머지

Fork 한 Remote 동기화 상세 예제

  • github 등에서 fork 했을 때 원본과 동기화하기
# 현재 상태의 확인
$ git remote -v
> origin  https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
> origin  https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
 
# 원본을 upstream 으로 추가
$ git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
 
# Remote가 잘 추가 됐는지 확인
$ git remote -v
> origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
> origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
> upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch)
> upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)
 
# upstream 최신화
$ git fetch upstream
 
# 내 리포리토리 master 체크아웃
$ git checkout master
 
# upstream/master 머지 - 끝
$ git merge upstream/master

Rebase

이미 공개 저장소에 Push 한 커밋을 Rebase 하지 마라
이 지침만 지키면 Rebase를 하는 데 문제 될 게 없다. 하지만, 이 주의사항을 지키지 않으면 사람들에게 욕을 먹을 것이다.
일반적인 해답을 굳이 드리자면 로컬 브랜치에서 작업할 때는 히스토리를 정리하기 위해서 Rebase 할 수도 있지만, 리모트 등 어딘가에 Push로 내보낸 커밋에 대해서는 절대 Rebase 하지 말아야 한다.
  • rebase라는 것은 현재 브랜치의 base가 되는 뿌리 커밋을 바꿔친다는 뜻이다.
    • 예를들어 master C5 에서 experiment 브랜치를 땄다면, experiment 브랜치의 Base가 되는 커밋은 C5이다.
    • experiment에서 이런 저런 작업을 하고 커밋을 하고(C7, C8 생성됐다 치고), 마스터에서도 작업을 해서(C6, C7, C10) 마스터의 커밋이 C10이 된 상태가 됐다.
    • experiment에서 master에 대해 rebase를 수행하면(git rebase master) 현재 experiment의 커밋들이 가리키는 base 커밋을 마스터의 C10으로 바꾸는 작업이다.
    • 이렇게 한 상태에서 master로 돌아가서(git checkout master), experiment를 머지하면(git merge experiment) 머지되는 커밋들이 C5에 대해 머지되지 않고, C10의 뒤로 머지되어 master 입장에서 봤을 때 C10 → C7' → C8'로 깔끔한 순서로 머지가 되는 것이다.
      • 만약 rebase없이 그냥 머지를 하면 master의 입장에서 봤을 때 C5 → C7 → C8 → C11(머지후 커밋) 가지와 C5 → C6 → C9 → C10 → C11(머지후 커밋) 이 두개의 가지가 생긴다.
      • 하지만 rebase를 하면 C5 → C6 → C9 → C10 → C7' → C8' → C11(머지후 커밋)으로 하나의 가지만 생기게 된다.
    • Rebase와 Merge 흐름
      • 부모(master로 간주)에서 pull을 실행해 최신으로 변경한다. : git pull
      • 작업 브랜치로 간다. : git checkout workingbranch
      • 작업 브랜치의 부모에 대해 rebase : git rebase master
      • 부모로 간다. : git checkout master
      • 작업 브랜치의 내용을 머지해 부모에 적용한다. : git merge workingbranch
  • --preserve-merges : rebase 시에 머지 커밋을 유지한다.

Tag

  • git fetch --tags : remote tag 목록 가져오기
  • git tag -l : 태그의 목록을 보여준다.
  • git tag -a [tagname] [commit] -m “태그 설명” : commit을 지정하지 않으면 현재 커밋.
  • git checkout tags/[tagname] -b [branchname] : 태그이름으로 로컬 브랜치를 체크아웃한다.
  • git checkout [tagname] : 태그 목록의 태그 이름을 이용해 해당 태그를 체크아웃한다.
  • git tag -d [tagname] : 태그 삭제
  • git push --tags : 태그 전체를 리모트로 푸시
  • git push origin [tagname] : 특정 태그를 리모트로 푸시
  • git push origin :[tagname] : 리모트 태그 삭제
  • git push --delete origin [tagname] : 리모트 태그 삭제
  • git describe --tags `git rev-list --tags --max-count=1` : 가장 최근 태그
  • git ls-remote --sort='version:refname' --tags [remoteurl] | tail --line=1 | cut --delimiter='/' --fields=3 원격 저장소에서 clone 받지 않고서 가장 최근 tag 가져오기

Merge

  • git merge [내용을 가져올 브랜치명] : 특정 브랜치를 현재 브랜치에 Merge
  • git merge [내용을 가져올 브랜치명] --squash; #충돌 처리 작업 후 ;git commit : 다른 브랜치로부터 머지를 하되 모든 커밋들을 하나로 뭉쳐서 가져온다. 실제 커밋은 현재 브랜치에서 commit 명령으로 생성한다. How to use git merge squash
  • git merge -Xignore-space-change [내용을 가져올 브랜치명] : 머지할 때 공백을 무시한다. -Xignore-all-space 도 가능. rebase시에도 동일한 방법으로 사용한다.
  • -Xignore-space-at-eol 참조
  • git merge –abort : 머지 중간 상태일 때 취소
  • git reset –hard HEAD : 머지 중간 상태일 때 취소

Stash

  • git stash : 스태시
  • git stash list : 스태시 목록
  • git stash pop : 마지막 스태시 복원하고 목록에서 제거

Patch

  • git apply 패치파일.patch

ls-files

Local bare repository

  • 로컬 파일시스템에 원격 리포지토리를 흉내내에 리포지토리를 만든다.
  • 정확히는 워킹 디렉토리가 없는 순수 리포지토리만 만드는 작업이 --bare 옵션이다.
    # 리포지토리 생성
    git init --bare newreponame
     
    # clone
    git clone newreponame [clonename]
  • 로컬 리포지토리를 사용해 Git 연습을 하기 좋다.

Merge branch 'master' of https://xxx...

  • 요약하면
    1. 원격지에서 내가 Pull을 한 뒤에 내 리포지토리에서 수정/커밋을 하고
    2. 그 사이에 (내가 Push)하기전에 다른 사용자가 자기의 변경 사항을 먼저 Push
    3. 내 수정 사항을 Commit하기 전에 먼저 Pull을 해야하는데, 이 때 다른 사용자의 변경사항이 머지 되면서 발생하는 커밋 로그.
    • pull --rebase를 하던가
    • git config --global branch.autosetuprebase always 혹은
    • git config branch.master.rebase true : master 대신 원하는 브랜치명

.gitignore

이미 한 add했던 파일은 ignore해도 적용이 안된다. 캐시돼 있기 때문이라고 한다. 이 때는 다음과 같이 처리한다.

git rm --cached 무시할파일명

alias

  • 원하는 명령을 짧게 줄이도록 할 수 있다.
# last
git config --global alias.last 'log -1 HEAD'
git config --global alias.lg \
 "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an %ae>%Creset' --abbrev-commit --"
 
git config --global alias.ci commit
git config --global alias.co checkout
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
 
# 외부명령 gitk 혹은 gitg
git config --global alias.visual '!gitk'

ignore

  • .gitignore : 특정 프로젝트 root 에 두고 해당 프로젝트의 모든 개발자가 공유하는 ignore 목록
  • .gitignore를 직접 편집 못할경우 .git/info/exclude 파일에 추가해주면 본인만 제외 처리할 수 있다.
  • core.excludesfile : 본인 계정에 전역으로 ignore
git config --global core.excludesfile ~/.gitignore-global

참조

git/cheatsheet.txt · 마지막으로 수정됨: 2024/02/06 09:18 저자 kwon37xi