# ~/.git-credential 내용이 osx의 키체인으로 등록된다.
# 현재 저장소의 키체인에 저정된 id,pw 를 확인한다.
git credential-osxkeychain get
git push -u origin master
# remote(origin) 저장소 변경
git remote set-url origin git://github.com/ysoftman
# 이미 존재하는 git repository 저장소를 로컬에 복사
# git 프로토콜 외 ssh, https 등 사용가능
# --recursive 옵션 사용시 링크된 repo 도 클론한다.
git clone git://github.com/ysoftman
# 클론 후 ysoftman1 브랜치로 체크아웃
git clone -b ysoftman1 git://github.com/ysoftman
# --single-branch 옵션까지 사용하면 해당 브랜치 커밋만 가져온다.
git clone -b ysoftman1 --single-branch git://github.com/ysoftman
# ssh 를 사용하는 경우
# 로컬에서 ssh 키 생성수 id_rsa.pub 를 github personal setting -> ssh and gpg key -> new ssh key 에 추가하고 다음과 같이 클론한다.
git clone git@github.com:ysoftman/ysoftman.git
# 파일 추가(스테이지에 올리기)
git add source_file.c
# 변경(수정,삭제) 있는 파일만 추가(tracked 파일중)
git add -u
# 전체 파일 추가(untracked 파일까지 포함)
git add -A
# 수정된 파일 자동 스테이지 추가하여 커밋
git commit -a
# 로컬 저장소에 반영(커밋)
git commit -m "commit comment."
# 마지막 커밋 내용 수정(push 이미 푸시 커밋은 수정하지 말자.)
git commit --amend
# 변경사항 없는 컷밋하기
git commit -m "no changes" --allow-empty
# a1234(git log 로 커밋 해시 확인) 커밋 되돌리기
# a1234 커밋 상태로 커밋한다.(자동 커밋되기 때문에 주의, reset 으로 커밋 취소 가능)
# a1234 revert 가 앞에 붙은 커밋 메시지를 사용한다.
git revert a1234
# 자동 커밋하지 않고 되돌리기
git revert --no-commit a1234
# 마지막 커밋 1개 되돌리기
git revert HEAD~1
# -X <option>, --strategy-option=<option>
# a1234(theirs)로 자동 커밋하지 않고 되돌리기
git revert -X theirs --no-commit a1234
# 머지 되돌리기
# 머지커밋을 보면 다음과 같이 브랜치의 시작(aaa)과 끝(ccc) 커밋이 명시되어 있다.
# Merge aaa ccc
# -m(--mainline) parent-number:머지된 브랜치의 시작 커밋aaa는 1이 된다.
git revert -m 1 머지커밋해시
# 현재 로컬 브랜치를 리모트에 푸시
git push
# pre-push hook 하지 않고 푸시하는 경우
git push --no-verify
# 현재 로컬 모든 브랜치를 리모트에 푸시
# 로컬 저장소 develop 브랜치를 리모트 저장소 develop 로 푸시
# git push {remote_name} {local_branch}:{remote_branch}
git push origin develop:develop
# 현재 로컬 모든 tag들 리모트에 푸시
# 리모트 저장소 브랜치 내용을 로컬 브랜치에 반영(fetch + merge)
git pull
# Fetch all remotes (브랜치가 최신으로 업데이트되지는 않는다.)
git fetch --all
# 또는
git pull --all
# 리모트 저장소 master 를 로컬 master 로 pull 받기(최신으로 업데이트)
git pull origin master
# pull request 내용 받기(123 은 pr 번호다.)
git pull origin pull/123/head:pr-123
# 커밋 로그 보기
git log
# 커밋 로그 diff 도 보기(-p --patch 패치 생성)
git log -p
# 커밋 로그 diff 최신 10개 이전까지만 보기
# log 보기 화면에서 / 로 검색할 수 있다. 예) /my\ name\ is\ ysoftman
git log -p -10
# HEAD 에 tracked 파일들 보기
git ls-tree HEAD
# 스테이지에서 빼기
git reset
# 또는
# 새로 생긴 커맨드로 reset 보다 권장된다.
git restore --staged 파일명
# push 되지 않은 최근 커밋1개 취소
git reset HEAD~1
# 소스가 꼬였을때 서버 기준으로 강제로 업데이트 받기(이클립스 설정파일에서 자주 발생)
git reset --hard HEAD
git pull
# 원격 push된 잘못된 바로 이전 커밋(내역) 삭제하기
# 헤드로부터 1개 전까지 커밋 삭제(1개 이전 상태로 되돌린다.)
# 원격으로 강제 push
git reset --hard HEAD~1
git push -f
# 더이상 사용되지 않는 리모트 브랜치 제거하고 가져오기
git pull --prune
# 또는
git fetch --prune
# 리모트 브랜치 리스트 파악
git branch -r
# 로컬 브랜치 리스트 파악
git branch -a
# git branch -a 로 보면 remotes/origin/xxx 가 나오는데
# 리모트에서 삭제된 브랜치들을 로컬에 적용해 삭제할 수 있다.
git remote update --prune
# 브랜치 생성
git branch ysoftmanbranch1
# 존재하는 브랜치 체크아웃(에러 발생시 -f 옵션으로 강제 스위칭 가능)
git checkout ysoftmanbranch1
# 브랜치 생성하고 생성된 브랜치로 이동(체크아웃)
git checkout -b ysoftmanbranch2
# origin에서도 삭제된 브랜치로 체크아웃
git checkout 삭제된_브랜치_이름 커밋_해시값
# 생성된 브랜치 원격으로 처음으로 푸시하는 경우
git push --set-upstream origin ysoftmanbranch2
# 원격 브랜치가 있는경우 로컬에 체크아웃
# -t(track) 이 없으면 커밋이 안되고, 다른 브랜치로 체크아웃시 원격 브랜치가 로컬에서 사라진다.(git pull 로 최신 상태여야 한다.)
git checkout -t {업스트림이름}/{브랜치명}
git checkout -t origin/ysoftmanbranch3
# 태그로 체크아웃
git checkout tags/1.0.0
# 브랜치 삭제(삭제할 대상외의 브랜치로 스위칭되어 있어야 한다.)
git branch -d ysoftmanbranch1
# 브랜치 이름 변경
git branch -m ysoftman_old_branch ysoftman_new_branch
# 브랜치 이름 변경후 원격에도 반영할때
# 원격 브랜치 삭제
git push origin -d ysoftman_old_branch
# 이름 변경된 브랜치 원격 반영할때
git push origin ysoftman_new_branch
# 로컬 저장소 현재 디렉토리에서 지워진 파일 리스트 보기
git ls-files -d
# 로컬 현재 디렉토리에서 지워지거나 수정된 모든 파일 복구(참고로 svn 인경우 svn up)
git checkout ./
# 로컬 현재 디렉토리에서 지워지거나 수정된 특정 파일만 복구
git checkout -- ysoftman_file1.txt
# 로컬 특정 파일만 특정 시점으로 복구
git checkout 커밋해시값 -- ysoftman_file1.txt
# 리모트 저장소 정보 확인
git remote -v
# 리모트 저장소에 저장소 추가
git remote add new_remote_name remote_URL
# untracked 파일 삭제
# -f force, -d (directory)
git clean -fd
# 커밋전에 차이 보기(-U10, --unified=10 위아래 내용 10줄씩 보기)
git diff -U10
# ysoftmanbranch1 브랜치의 aaa.txt 파일과 차이 보기
git diff ysoftmanbranch1 -- aaa.txt
# 현재 상태
git status
# 현재 환경 상태
git show
# 커밋 내용 보기
git show 커밋해시
# 현재 변경내용 저장하고 HEAD 상태로 되돌리기
git stash save
# 변경 리스트 보기
git stash list
# 변경 내용 보기
git stash show
# 변경 내용 적용하기(stash 에 계속 유지)
git stash apply
# 변경 내용 꺼내기(stash 에서 삭제됨)
git stash pop
# a1234 b555 커밋 master 에 반영하기
git checkout master
git cherry-pick a1234 b555
# 로컬 태그 리스트
git tag
# 로컬 태그 원격 태그로 푸시
git push origin 1.1.1
# 원격 태그 리스트
git ls-remote --tags
# 로컬 태그 삭제
git tag --delete 1.1.1
# 로컬 0.0.1로 시작하는 태그 모두 삭제
git tag | grep "^0.1.1.*" | xargs git tag --delete
# 원격 태그(들) 삭제
git push --delete origin 1.1.1 1.1.2 1.1.3
# 또는 빈 태그를 푸시해도 삭제 된다.
git push origin :refs/tags/1.1.1
# 원격 태그 0.0.1로 시작하는 태그 모두 삭제
git ls-remote --tags | awk '{print $2}' | sed 's/refs\/tags\///' | grep "^0.0.1.*" | xargs git push --delete origin
# 0.0.1로 시작하는 태그들 로컬 태그삭제 후 원격태그도 삭제
delete_tags=$(git tag | grep "^0.1.1.*")
echo $delete_tags | xargs git tag --delete
echo $delete_tags | xargs git push --delete origin
# 대소문자 파일이름 변경
git mv --force ysoftman.TXT ysoftman.txt
#####
# 머지시 충돌 해결하기
# develop 을 최신으로 pull 해놓고 ysoftman123 에서 시작
git checkout develop
git pull
git checkout ysoftman123
# 방법1 - merge (커밋 히스토리 유지)
# develop -> ysoftman1 로 머지
git merge develop
# 충돌 부분 수정 수정
vim aaa.txt
# 또는
# develop <- ysoftman123 머지 상황에서 전략 옵션 사용하기
# -X <option>, --strategy-option=<option>
# 충돌부분 ysoftman123(theirs)로 덮어쓰기
git checkout develop
git merge -X theirs ysoftman123
# 또는
# 충돌부분 develop(ours)로 유지
git merge -X ours ysoftman123
# 커밋하고 푸시(커밋 메시지는 기본적으로 충돌 해결 내용으로 채워진다.)
git commit -a
git push
# 머지 취소할 경우
git merge --abort
# git pull 후 충돌발생시 머지 취소 후
# 현재 내가 변경한 사항으로 pull(머지)하기
git pull -s recursive -X ours
# 방법2 - rebase (ysoftman123 의 커밋들이 develop 이후 커밋들로 강제 변경된다.)
# ysoftman123 브랜치에서 develop 으로 rebase
git rebae develop
# 충돌 나는 부분을 확인
git status # 충돌되는 부분은 both modified 로 표시
git diff
# 충돌 부분 수정
vim aaa.txt
# 커밋(커밋 메시지는 기본적으로 충돌 해결 내용으로 채워진다.)
git commit -a
# rebase 계속해서 rebase 종료
git rebase --continue
# 강제 푸시, --force-with-lease 는 내 로컬에서 수정된게 아니면 덮어쓰지않아 --force 보다 안전하다.
git push --force-with-lease
#####
# 저장소 이전(migration)
# old 저장소 bare 로 클론 받기
git clone --bare https://github.com/ysoftman/old-repository.git
# new 저장소로 mirror 푸시
cd old-repository.git
git push --mirror https://github.com/ysoftman/new-repository.git
# old 저장소 삭제
cd ..
rm -rf old-repository.git
#####
# github wiki 이전
# old 저장소 wiki 클론 받기
git clone https://github.com/ysoftman/old-repository.wiki.git
# remote origin 을 new 저장소로 바꾸기
git remote set-url origin https://github.com/ysoftman/new-repository.wiki.git
# new 저장소 github -> wiki 생성하기
# Initial Home page 커밋이 발생하지만 강제 푸시하면 old 커밋히스토리만 남게된다.
# 참고로 -f 옵션없으면 "관계 없는 커밋 내역의 병합을 거부합니다" 에러가 발생한다.
git push -f
#####
# 패스워드 같은 민감한 데이터가 커밋,푸시돼 커밋히스토리 제거가 필요할때
# 모든 브랜치 및 태그에서 password.txt 파일 삭제 전 참고 및 주의사항
# 커밋에 password.txt 파일만 수정이 있었다면
# 커밋 히스토리 자체가 제거된다.
# 커밋에 password.txt 외 다른 파일 수정이 있었다면
# 커밋 히스토리는 있고 커멋내용에서 password.txt 파일만 제거된다.
# 로컬에 password.txt 도 삭제되니 rename 으로 백업해두자.
cp -v password.txt password.txt.bak
git filter-branch --force --prune-empty --index-filter 'git rm --cached --ignore-unmatch password.txt' --tag-name-filter cat -- --all
# 이제 강제 push 하면 원격 저장소에도 password.txt 관련 커밋 히스토리 또는 내용이 삭제된다.
git push -f
# filter-branch 삭제 후 원격 저장소에는 삭제됐지만
# 로컬 커밋 히스토리(git log --all)로 refs 모두를 보면 다음과 같이 백업이 있다.
# 참고로 git 은 ./git/refs 에 커밋해시(sha1,40자리의 hexadecimal)값 파일을 저장해 관리 한다.
refs/original/refs/remotes/origin/master
refs/original/refs/heads/master
# 로컬 .git/refs 에 백업된 refs 삭제
git update-ref -d refs/original/refs/remotes/origin/master
git update-ref -d refs/original/refs/heads/master
#####
# rebase 로 브랜치 합치기(커밋들이 대상 브랜치(master)의 마지막 커밋 이후로 변경돼 커밋 이력이 깔끔해 진다.)
# ysoftmanbranch1 이 master 에 머지되기전
# ysoftmanbranch1 에서 master 로 rebase
# ysoftmanbranch1 브랜치가 아닌 master 로 기반으로 파생된 커밋으로 된다.
git checkout ysoftmanbranch1
git rebase master
# 만약 충돌이 발생하면, 충돌 수정후 rebase 계속
git rebase --continue
# 현재 HEAD 는 ysoftmanbranch1 커밋이다.
# master 에서 ysoftmanbranch1 을 머지하여 master 가 HEAD 가 되도록 한다.
git checkout master
git merge ysoftmanbranch1
# 만약 로컬에서 rebase 완료했는데 취소하고 싶다면 reflog 로 최근 rebase.. 바로전으로 HEAD 확인
git reflog
aaa111 HEAD@{1}: rebase: commit message
aaa222 HEAD@{2}: rebase: commit message
aaa333 HEAD@{3}: rebase: commit message
aaa444 (master) HEAD@{4}: rebase: checkout master
aaa555 (HEAD -> branch_test) HEAD@{5}: rebase: commit message
# reset 으로 rebase 전의 head 로 돌리면 된다.
git reset HEAD@{5}
# 참고로 위처럼 reflog 는 reset 외 commit 등 HEAD 변경 내용이 모두 기록된다.
#####
# fork 저장소에서 작업시
# 원본 저장소 최신 내용 fork 저장소에 반영하기
# upstream 으로 원래 저장소 추가
git remote add upstream "https://원본저장소"
git remote -v
# upstream 저장소 삭제
git remote remove upstream
# upstream 최신 내용 가져오기
git fetch upstream
# fork master 브랜치에 upstream 내용 머지
git checkout master
git merge upstream/master
# 현재 브랜치 upstream 으로 push 하기
git push -u upstream
#####