Git 사용법 총 정리

사요·2021년 9월 18일
1

git bash

// git commit에 사용될 username
git config --global user.name "your_name"
 
// git commit에 사용될 email
git config --global user.email "your_email@example.com"
 
// 설정한 내용을 확인할 수 있다.
git config --list

git clone 주소명 : 초기 파일 다운로드 받기
git init : 현재 레포지토리를 버전관리하겠다.

git commit vs. git add
git add 명령어는 다음 변경(commit)을 기록할 때까지 변경분을 모아놓기 위해서 사용
따라서, git commit 명령어를 통해 명시적으로 기록을 남기기 전까지는 아무리 git add 명령어를 많이 실행해도 Git 저장소의 변경 이력에는 어떤 영향도 주지 않습니다.


클론을 받은 컴퓨터도 하나의 저장소로서 역할을 수행하게됨.
로컬저장소(리포지토리):우리컴퓨터
원격저장소 : 깃홈페이지에 있는 저장소

여러가지 깃 명령어

ls -al :생성된 파일목록
vim 파일명.확장자 : 파일생성
cat 파일명.확장자 :파일보기
git status : 파일들이 버전관리 되고있는지 여부. untracked ->추적되지 않고있다.
git add 파일명.확장자 : git에게 이 파일을 버전관리하라고 명령함. 관리해야할파일이 무엇인지 정확하게 깃에게 알려줌. add를 통해 선택적으로 파일을 커밋할 수 있음.

버전 vs 변화
: 버전은 의미있는 변화! 어떤 작업이 완결된 상태.

📸커밋 (Commit)


: Git 저장소에 디렉토리에 있는 모든 파일에 대한 스냅샷을 기록하는 것.각 커밋은 저장소의 이전 버전과 다음 버전의 변경내역("delta"라고도 함)을 저장

resolving deltas :저장소를 복제(clone)하려면 모든 변경분(delta)를 풀어내야 하는데, 이 때문에 명령행 결과로 볼 수 있습니다.

git commit :커밋하기
git commit -m 'message'
stage area :커밋대기하는 파일들이 가는곳
repository :커밋이 된 결과가 저장되는곳

🎄 브랜치 (branch)

:특정 커밋에 대한 참조(reference), 하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역

" 브랜치를 서둘러서, 그리고 자주 "
브랜치를 많이 만들어도 메모리나 디스크 공간에 부담이 되지 않기 때문에, 작업을 커다른 브랜치로 만들기 보다, 작은 단위로 잘게 나누는 것이 좋다.
git branch [브랜치명] : 브랜치 만들기
git checkout [브랜치명] : 새 브랜치로 이동
git merge [브랜치명] :두 개의 부모(parent)를 가리키는 특별한 커밋.두 부모의 모든 부모들의 작업내역을 포함. 현재 브랜치를 브랜치명이 가리키는 브랜치에 합병시킴

<예시>

git merge bugFix : bugFix를 현재(main)브랜치에 머지
->main이 두 부모가 있는 커밋을 가리킴.

git checkout bugFix; git merge main : bugFix브랜치로 이동한다음 main브랜치에 bugFix를 머지.

즉 메인에서 타브랜치를 머지 = 타브랜치에서 메인을 머지

Q. git merge bugFixgit merge main 의 차이점?

원격 저장소 (Git Remote)

:또 하나의 컴퓨터에 있는 여러분의 저장소의 복사본. 백업으로서의 역할을 훌륭하게 수행. 프로젝트의 복사본이 어느 곳에선가 호스트되기 때문에 여러사람과 작업 가능.

git clone :원격저장소를 로컬에 복제한다. 로컬저장소에 새 브랜치가 생긴다.이런 종류의 브랜치를 원격브랜치라고 한다.

원격저장소(클라우드) <---> 원격 브랜치(로컬)
클라우드가 변하면 로컬도 같이변하지만
로컬이 변한다고 클라우드가 변하지는X

원격 브랜치의 이름짓기 형식

<remote name>/<branch name>
ex) origin/main라는 이름의 브랜치를 보게되면, 브랜치의 이름은 main이고 원격 저장소의 이름은 origin인겁니다.

main -> 원격 저장소의 main브랜치를
o/main -> 원격 저장소의 main브랜치를 가리키는 로컬저장소의 o/main 브랜치

Git Fetch

:원격 저장소에서 데이터를 가져오는 방법. 즉, 로컬에서 나타내는 원격 저장소의 상태를 실제 원격 저장소의 (지금)상태와 동기화 우 리가 원격 저장소와 작업을 해서 상태가 변하면 원격브랜치들 또한 그 변경들을 반영

  1. 원격 저장소에는 있지만 로컬에는 없는 커밋들을 다운로드 받습니다.
  2. 그리고 우리의 원격 브랜치가 가리키는곳을 업데이트합니다

git fetch는 그러나, 여러분의 로컬 상태는 전혀 바꾸지 않습니다.
이것을 이해하는게 아주 중요한데, 왜냐하면 수 많은 개발자들이 git fetch를 하면 자신의 로컬 작업이 변경되어 원격 저장소의 모습을 반영해 업데이트 될것이라고 생각하기 때문입니다. 앞의 과정에 필요한 데이터를 다운로드는 하지만, 실제로 로컬 파일들이나 브랜치를 변경하지는 않습니다.

->그럼 어떻게 로컬상태를 바꾸지? 작업을 업데이트! FULL로!

Git pull

: 작업을 업데이트해서 변경들을 반영. 사실 원격 저장소의 변경을 fetch하고 그이후에 merge하는 작업의 과정이 워낙 자주있는 일이라서 git은 이 두가지를 한번에 하는 명령을 제공. 즉, git pull은 본질적으로 git fetch후에 내려받은 브랜치를 병합하는 과정의 단축.

<여러가지 방법>

  • git cherry-pick o/main
  • git rebase o/main
  • git merge o/main

원격 저장소는 자신의 main 브랜치에 대한 직접적인 커밋을 제한합니다. 왜냐하면 push 대신에 pull request가 쓰여야 한다는 규칙이 원격 저장소의 main 브랜치에는 적용되어 있기 때문이죠.

여러분은 브랜치를 따로 만들어 작업한 다음, 그것을 push하고 pull request를 하려 했습니다. 하지만 그걸 잊고 실수로 main 브랜치에서 직접 커밋을 해버렸네요! 이제 변경 사항을 push 하지도 못하고 옴짝달싹 못하는 상황이 되어버렸습니다.
feature 라는 이름의 다른 브랜치를 만들어 원격 저장소에 push 하세요. 그리고 원격 저장소와 동기화될 수 있도록 로컬 저장소의 main 브랜치를 reset하세요. 그렇지 않으면 여러분이 다음에 pull을 시도할 때 문제가 발생하거나, 다른 협업자들의 커밋이 여러분의 커밋과 충돌할 수도 있습니다.

Git Push

:작업을 업로드해 공유하는것.여러분의_변경을 정한 원격저장소에 업로드하고 그 원격 저장소가 여러분의 새 커밋들을 합치고 갱신하게 합니다.
만일 원격저장소에 새로운 작업이 추가되어있다면 작업을 공유하기전에 원격 저장소의 최신 상태를 합치도록 강제합니다.
ex) 유니티에서 올리기전에 sync 를 하는것과 같음.

따라서 여러분의 작업을 원격 브랜치의 최신상태를 기반으로 하게 만들면 됩니다.

'git fetch; git rebase o/main; git push'
'git fetch; git merge o/main; git push'
'git pull--rebase; git push`
: fetch -> rebase or merge -> push

git pull--rebase : fetch와 리베이스를 하는 작업의 줄임 명령어

🛠리베이스(Rebase)

:브랜치끼리의 작업을 접목. 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것. 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점.저장소의 커밋 로그와 이력이 한결 깨끗. 브랜치에 메인으로 복사하고싶은 작업이 있을때.
git rebase <브랜치1>: 지금 가리키고 있는(HEAD)의 커밋들을 모아서 브랜치1(베이스) 위에 떨굼.

git rebase <브랜치1> <브랜치2>: 브랜치 1(베이스)위에 브랜치 2커밋 떨구기

git rebase main : bugFix 브랜치에서의 작업을 main 브랜치 위로 직접 옮김 (대상을 선택하지 않으면 자동으로 main이 되는듯)

->bugFix 브랜치의 작업 내용이 main의 바로 위에 깔끔한 한 줄의 커밋으로 보이게됨.
git rebase bugFix : main이 bugFix의 부모쪽에 있었기 때문에, 단순히 그 브랜치를 더 앞쪽의 커밋을 가리키게 이동하는 것.

리베이스와 머지의 차이점?
:갈래로 나누어지지 않는다.

q.이상태에서 버그픽스에서 git rebase 하는거랑 메인에서 git rebase bugFix 하는거랑 뭔차이?
1.버그픽스에서git rebase

2.메인에서git rebase bugFix = bugFix를 베이스로한다
: 메인 브랜치의 작업 내용이 bugFix바로 위로 올라감.

👑헤드(HEAD)

:현재 체크아웃된 커밋. 즉 현재 작업중인 커밋.HEAD는 항상 작업트리의 가장 최근 커밋을 가리킴. HEAD =브랜치의 이름을 가리킴

HEAD 분리하기
:HEAD를 브랜치 대신 커밋에 붙이는 것.각 커밋은 그것의 해시값으로 특정지을수 있다.
git chekcout [해시값]

git log : 해시확인 ex)fed2da64c0efc5293610bdd892f82a58e8cbc5d8 = fed2

그러나 커밋들을 해시로 구분하고 사용하는것은 편한일이 아니다.
이때 Git의 상대 참조(Relative Ref)를 이용한다.

🔭상대 참조(Relative Ref)

: 우리가 기억할 만한 지점(브랜치 bugFix라던가 HEAD라던가)에서 출발해서 이동하여 다른 지점에 도달해 작업. 브랜치를 옮길 때 일반적으로 사용.

상대커밋
:HEAD^를 통해 시간을 거슬러 올라갈 수 있다!

  • 한번에 한 커밋 위로 움직이는 ^ :참조 이름에 하나씩 추가할 때마다, 명시한 커밋의 부모를 찾게됨.
    ex) main^는 "main의 부모"와 같은 의미 ,main^^ 는 "main의 조부모(부모의 부모)"를 의미.
  • 한번에 여러 커밋 위로 올라가는 ~[num] : 틸드 연산자는 (선택적) 올라가고 싶은 부모의 갯수가 뒤에 숫자가 옴
    ex) git checkout HEAD~4 : HEAD가 HEAD로부터 4칸 거슬러 올라간 커밋을 가리키게됨.

    버픽 헤드 메인

▶브랜치를 특정 커밋에 직접적으로 재지정하기 (브랜치 강제로 옮기기 )
git branch -f 브랜치1 브랜치2 : 브랜치1을 브랜치 2로 옮긴다.

1.git branch -f main HEAD~3 : main 브랜치를 HEAD에서 세번 뒤로 옮김.

2. 상대 참조를 통해 C1을 간결한 방법으로 참조할 수 있었고 브랜치 강제(-f)를 통해 브랜치를 저 위치로 빠르게 옮길 수 있다.

헤드가 분리되어있는 상태에서는 checkout 브랜치명이 불가능. checkout 해시값만 가능.git
git branch -f main : 메인브랜치를 현재 헤드가 가리키고 있는곳으로이동

♻작업 되돌리기

git reset : 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식.히스토리를 고쳐쓴다. 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것.
git reset HEAD~1 한결과

git revert : 각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없다. 변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 공유하기 위해서는, git revert를 써야한다.
git revert HEAD 한결과

: 전 작업사항으로 다시 커밋하는것.

Q.둘의 차이점이 뭔가요. C2' 가 C1을 의미하는게 맞나요?

Q.둘은 같나요?

커밋된 내역은 변경사항만을 의미하나요 아니면 변경사항까지 포함한 전체 작업 내역을 의미하나요

🍒 Git cherry-pick

: 몇개의 커밋만을 여러개의 브랜치들에서 main 브랜치로 복사해야할때 사용.
원하는 커밋이 무엇인지 알때(각각의 해시값도) 아주 유용.

git cherry-pick <Commit1> <Commit2> <...> :현재 위치(HEAD) 아래에 있는 일련의 커밋들에대한 복사본을 만들겠다는 것.
-> 즉 ,commit1 ,commit2 ... 를 메인 브랜치에 복사해줌


💎Interactive Rebase

:원하는 커밋을 모르는 상황. 리베이스할 일련의 커밋들을 검토할 수 있는 가장 좋은 방법. 인터렉티브 리베이스가 의미하는 뜻은 rebase 명령어를 사용할 때 -i 옵션을 같이 사용한다는 것.이 옵션을 추가하면, git은 리베이스의 목적지가 되는 곳 아래에 복사될 커밋들을 보여주는 UI를 띄울것 .각 커밋을 구분할 수 있는 각각의 해시들과 메시지도 보여줌.

*기능


git rebase -i HEAD~4 : HEAD로부터 4개의 작업내역을 검토하고 REVASE한다. 리베이스할 타겟으로 브랜치가 상대참조(HEAD~)를 사용할 수 있다.

로컬에 쌓인 커밋 해결하기

:개발 중에 종종 이런 상황이 생깁니다: 눈에 잘 띄지 않는 버그를 찾아서 해결하려고, 어떤 부분의 문제인지를 찾기 위해 디버그용 코드와 화면에 정보를 프린트하는 코드 몇 줄 넣습니다.디버깅용 코드나 프린트 명령은 그 브랜치에 들어있습니다. 마침내 버그를 찾아서 고쳤고, 원래 작업하는 브랜치에 합치면 됩니다!
이제 bugFix브랜치의 내용을 main에 합쳐 넣으려 하지만, 한 가지 문제가 있습니다. 그냥 간단히 main브랜치를 최신 커밋으로 이동시킨다면(fast-forward) 그 불필요한 디버그용 코드들도 함께 들어가 버린다는 문제가 생깁니다.

<가장 간단한 두가지 해결방법 >
git rebase -i :대화형 (-i 옵션) 리베이스(rebase)로는 어떤 커밋을 취하거나 버릴지를 선택할 수 있습니다. 커밋의 순서를 바꿀 수도 있다. 어떤 작업의 일부만 골라내기에 유용.
git cherry-pick :어떤 커밋이던 골g라서 HEAD위에 떨어뜨릴 수 있다.

  1. 딱 한개의 커밋만 가져오기

:위와같은 상태에서 bugfix 커밋만 가져오고 싶다면?
1)git rebase -i 이용
git rebase -i HEAD~3' : C4커밋만 가져온후에 git branch -f main` :메인브랜치가 헤드를 가리키도록한다.
2)git cherry-pick 이용

이전 커밋 내역 바꿔서 적용하기

:newImage와 caption 브랜치에 각각의 변경내역이 있고 서로 약간 관련이 있어서, 저장소에 차례로 쌓여있는 상황입니다. 때로는 이전 커밋의 내용을 살짝 바꿔야하는 골치아픈 상황에 빠지게 됩니다. 이번에는 디자인 쪽에서 우리의 작업이력(history)에서는 이미 한참 전의 커밋 내용에 있는 브랜치(newImage)의 크기를 살짝 바꿔 달라는 요청이 들어왔습니다.

<해결방법>
1. git rebase -i 명령으로 우리가 바꿀 커밋을 가장 최근 순서로 바꾸어 놓습니다
rebase -i 명령으로 커밋의 순서를 바꿀 수 있습니다. 정정할 커밋이 바로 직전(top)에 있으면 간단히 --amend로 수정할 수 있고, 그리고 나서 다시 원하는 순서로 되돌려 놓으면 됩니다.

  1. git commit --amend: 명령으로 커밋 내용을 정정합니다. 원래꺼 삭제하고 새로운 갈래 만듬.
  2. 다시 git rebase -i 명령으로 이 전의 커밋 순서대로 되돌려 놓습니다
  3. 마지막으로, main을 지금 트리가 변경된 부분으로 이동합니다.

Git 태그

:프로젝트의 역사(작업 이력)에서 중요한 지점들에 영구적으로 표시를 할 방법.주요 릴리즈나 큰 브랜치 병합(merge)이 있을때. Git 태그는 특정 커밋들을 브랜치로 참조하듯이 영구적인 "milestone(이정표)"으로 표시. Git 태그는 커밋들이 추가적으로 생성되어도 절대 움직이지 않는다. 태그는 커밋 트리에서 특정 지점을 표시하기위한 닻같은 역할.

git tag <태그명> <붙일커밋>


⚜🔰🔬🔭▶➡🧶🎄

Git Describe

: git에는 여러분이 가장 가까운 "닻(태그)"에 비해 상대적으로 어디에 위치해있는지 describe(묘사)해주는 명령어.Git describe는 커밋 히스토리에서 앞 뒤로 여러 커밋을 이동하고 나서 커밋 트리에서 방향감각을 다시 찾는데 도움을 줌. 이런 상황은 git bisect(문제가 되는 커밋을 찾는 명령어라고 간단히 생각하자)를 하고 나서라던가 휴가를 다녀온 동료의 컴퓨터에 앉는경우
git describe <ref> :에는 commit을 의미하는 그 어떤것이던(커밋의해시값,브랜치) 쓸 수 있습니다. 만약 ref를 특정 지어주지 않으면, git은 그냥 지금 체크아웃된곳을 사용합니다 (HEAD).

명령어의 출력은 다음과 같은 형태로 나타납니다:

<tag>_<numCommits>_g<hash> : tag는 가장 가까운 부모 태그를 나타냅니다. numCommits은 그 태그가 몇 커밋 멀리있는지를 나타냅니다. <hash>는 묘사하고있는 커밋의 해시(ref가 가리키는 커밋의 해시값, 현재해시.)

여러브랜치들을 rebase하기

: 여러 브랜치들의 모든 작업내역을 main 브랜치에 리베이스할때. re

Q.아래와 같은 상황에서 git rebase another side 을 하면?


: side가 한칸 이동한다. 그 이유는 another을 베이스로 side의 커밋하기 때문이다.

다수의 부모가 있을때 특정부모로 거슬러올라가는법

활용1. 단독으로
:Git은 보통 병합된 커밋에서 "첫" 부모를 따라갑니다. 하지만 ^수식을 숫자와 함께 사용하면 앞의 디폴트 동작대로가 아닌 다른 결과가 나타납니다.


활용 2. 수식을 같이 사용

ex) git checkout HEAD~^2~ : 한칸뒤로, 두번째꺼 선택후, 한칸 더뒤로 헤드이동
-> ~ , ^2 , ~ 구분해서 생각하기!
ex) git branch bugWork main~^2~ : bugWork라는 브랜치를 만들건데 main에서 ~^2~만큼이동한 곳에 만들어라. 이때 포인터는 변경되지 않는다.

브랜치 스파게티

: main 브랜치의 몇 번 이전 커밋에 one, two,three 총 3개의 브랜치가 있습니다. 어떤 이유인지는 몰라도, main의 최근 커밋 몇 개를 나머지 세 개의 브랜치에 반영하려고 합니다.
one 브랜치는 순서를 바꾸고 C5커밋을 삭제하고, two브랜치는 순서만 바꾸며, three브랜치는 하나의 커밋만 가져옵시다!

✒📤🧾📜📗📕📘💡💾⛏🛠🔑🔏🔊🌈🔥🚩💫❓❗🔰♻✅✔🟥🟧🟨🟩🟦🟪🔺🖼🎞🎨🎗🔑⚠❔🔀↪➰💱🔴🔴🟠🟡🟢🔵🟣🟤⚫🗨🗝🔑🔨🔐🛠🎬🕯📸🔖👾👻✔👑💎

profile
하루하루 나아가는 새싹 개발자 🌱

0개의 댓글