제로타이 2022. 10. 18. 23:19

깃헙 특강 by 이고잉

git diff를 쓰면 커밋되지 않은 것과 현 커밋 간의 차이를 볼 수 있다. 

수정한 파일과, 새로 만들어진 파일은 스테이징되고 status를 찍어보면 다르게 표시된다.

이때 add 과정을 거치지 않고 commit -a 옵션을 넣어서 바로 커밋할 수 있다.
이때 work4.txt는 커밋되지 않는데, -a 옵션은 한번이라도 tracked(add된 이력 있는)된 파일만 autoadd를 시키고 커밋을 하기 때문. 왜 이렇게 나뉠까? 왜냐하면 자동으로 커밋되면 안 되는 파일이 존재하기 때문이다. 가령 유저의 개인 정보를 담고 있는 파일이 따로 있다면 그것은 함부로 커밋하면 안 된다. 그래서 그런 파일이 autoadd되는 것을 막기 위해 tracked여부가 구분되는 것. 

add에는 3가지 의미가 있다. 

  1. add의 첫번째 의미는 comit 대기 상태를 만드는 것이다.
  2. 두번째 의미는 untracked를 tracked로 만드는 것이다.
  3.  충돌을 해결했다는 것을 깃에게 알린다. 이것은 나중에 볼 것이다.

사실 work4와 work1의 수정은 같은 커밋으로 들어가는 게 맞다. 그런데 이미 커밋되어버려서 이를 수정하는 과정이 필요하다. 마지막 커밋을 수정하는 방법은 나중에 보게 될 것.

우리는 password는 절대로 커밋시키고 싶지 않다. 근데 git add . 을 쓰면 걸핏하면 같이 스테이지에 올라가게 될 것이다. 이때 쓰는 것은 바로 .gitignore!

.gitignore

약속된 무시파일! 이것을 깃에 올려주면 이제부터 password.txt는 철저하게 무시될 것이다!
참고! .gitignore가 없던 시점으로 checkout하면? password는 깃에 의해 관리되지 않으니 커밋을 바꾸건 말건 그대로 남아있을 것이고 근데 그 과거에는 .gitignore가 없기 때문에 password.txt가 다시 깃에 노출된다. 조심하라!

마지막으로 작업한 내용을 버리고 싶을 때는 어떻게 할까? 현재 버리고 싶은 버전은 마스터 브랜치의 끝자락. 단순한 방법은 바로 마스터 브랜치가 가리키는 버전을 이전으로 바꾸면 된다. 그러면 현재 커밋했던 것은 그냥 사라지는 꼴이 된다. 이때 사용하는 것이 reset! checkout은 헤드를 옮기고, reset은 헤드가 가리키는 브랜치를 옮긴다(이 둘의 차이를 잘 이해하고 있다면 충분히 깃 중급자).
참고로 reset은 브랜치를 옮기는 명령어이기에 반대로 없앴던 버전을 복구하는 것조차 가능하다.
또 참고로 reset은 아예 자신이 왔던 길이 아닌 새로운 브랜치 방향으로도 갈 수 있게 해준다.

git reset --hard <버전 커밋 id>

이러면 간단하게 마스터 자체가 가리키는 버전이 바뀐다. 다시 되돌리고 싶다면? reflog로 버린 id를 다시 확인해서 돌려놔야 한다..
유의하자. 만약 헤드가 브랜치에 있는 상태라면 브랜치의 위치가 바뀐다. 그러나 헤드가 detached상태라면? 이때는 checkout과 동일한 동작을 한다. 결국 reset이라는 것도 헤드를 기준으로 동작을 하는 녀석이기 때문에 그렇다. 

이제 본격적으로 병렬 작업을 진행해보자. 나중에는 걸핏하면 브랜치를 이용해서 작업을 하게 될 것이다. 왜냐? 버리기 쉽거든.

참고로 gui에서는 checkout옵션을 주면 쉽게 브랜치를 만들자 마자 checkout까지 시킬 수 있다. cli에서는 checkout 하면서 -b 옵션을 주면 된다!

git log --oneline --all --graph

이렇게 입력하면 cli에서도 여차저차 그래프 모양을 표현해준다.

git config --global alias.l 'log --oneline --all --graph'

놀랍게도, 깃 자체 설정을 통해  alias를 할 수 있다! 이제는 git l만 치면 내가 원하는 그림을 볼 수 있다.
만약 되돌리고 싶다면 홈 파일에 있는 .gitconfig파일에서 alias라 써있는 부분을 지워주면 된다!
--global 옵션을 빼면 현재 저장소에 대해서만 사용하는 alias가 될 것이다.

reset을 할 때는 이렇게 HEAD가 지났던 순서를 이용해서도 접근할 수 있다.

merge를 이용해 병합을 한다. 근데 같은 파일이 다르게 쓰여있는 버전 둘이 합쳐질 때는 충돌이 발생한다. 이를 어떻게 해야할까? 이것을 잘 처리해야 깃을 잘 사용할 수 있다.
다행이 그냥 추가되는 내용에 대한 병합은 문제 없이 이뤄진다.

원래 값은 1 2 3 4로 돼있었고, 마스터에서 2를 m2로, exp 브랜치에서 3을 e3로 바꾼뒤에 마스터에서 머지한다면, 단순하게 e가 추가된채로 머지가 된다!
그러나 문제는 똑같은 부분이 수정되었을 때이다. exp에서는 4를 e4로, 마스터에서는 m4라고 하고 머지하면?

이런 상황이 나온다! 마스터에 헤드가 놓여있어 헤드가 마스터의 변경사항에 맞춰서 보여주고 있다. 그리고 exp에서 오는 것을 incoming으로 보여주고 있다. 
자동병합을 하려는데 충돌이 생겨 문제가 발생했으니 사람더러 해결해달라고 징징대고 있는 것이다. 이건 우리가 수정해서 add를 하고 커밋을 해주면 해결된다! 이것이 바로 add의 세번째 역할이다. 

3way merge: 남의 커밋과 나의 커밋을 할 때, 공통 조상을 참조하는 것. 위에서 단순하게 변경사항이 추가되는 채로 병합될 수 있는 이유가 여기에 있다 둘의 공통조상을 비교하고, 이쪽에서는 바뀌지 않은 것이 저쪽에서만 바뀌었다면 그것을 변경사항을 인식하고 그것을 반영하는 것. 물론 양쪽에서 변경이 일어났다면 당연히 충돌이 일어나 사람이 해결해주어야만 한다.

깃의 주요한 기능은 3가지 정도가 된다. 버전 관리, 병렬 작업, 그리고 협업!
이제는 협업을 하는 방법에 대해 알아볼 차례이다. 

흔히 쓰는 github을 사용하자.

여기 써있는 것이 내 원격 깃 저장소의 주소이다. https와 ssh는 통신 방법을 이야기하는 것인데, ssh가 조금 더 간단하니 이쪽으로 쓰자.

git remote add origin git@github.com:Zerotay/egoing-ping.git

내 로컬에서 이렇게 remote를 해주면된다. add origin은 원격 저장소의 이름을 지정하는 것. 굳이 안 써도 알아서 origin으로 써진다고 알고 있다.

이렇게 되면 잘 된 것.

처음에는 우리의 마스터 브랜치가 원격에서 어떤 것과 페어링 될 것인지 직접 지정해줘야 한다. 나와있는 명령어를 그대로 쳐주기만 하면 내 마스터 브랜치가 원격 저장소의 마스터와 잘 연결된다.

멋모르고 쓰던 시절 많이 봤던 문구들.

사실 지금도 잘 모른다. 😅
이제부터는

git log를 칠 때 이렇게 origin master가 빨간 글씨로 나오는것을 확인할 수 있다! 어느 버전까지 원격에 올라가 있는지 표시돼있는 것.

보다시피 로컬에서만 커밋하고 원격으로 푸쉬하지 않았다면 헤드와 origin은 분리된다. 심지어 밑에 푸쉬할 게 남았다고 보여주기까지 한다.
헉.. git push origin master가 아니라 그냥 git push만 해도 잘만 올라간다.. 이거 진짜 처음 알았네

커밋을 수정하는 기능이 있다. --amend를 이용하면 쉽게 커밋을 바꿀 수 있다. 그러나 사실 그것은 정확하게 말하자면 현재 커밋을 복제하고 변경된 새로운 커밋을 만드는 것과 같다. 실제로 보면 커밋 id가 다르다. 

git commit --amend -m 'work seven'

가령 이렇게 하면 마지막 커밋한 것의 메시지를 다른 것으로 바꾸는 것이다. 그래도 분명히 원본은 남아있다는 것을 유의하라!
그리고 또 알아야 할 것. 이렇게 amend 옵션으로 바꿀 수 있는 커밋은 원격 저장소로 푸쉬되지 않은 것에만 한정된다.

로컬에서 원격으로 보낼 때는 push, 받을 때는 pull.

일단 연습을 위해.. 혼자서 원격 저장소와 연결된 두 디렉을 만들고, 한쪽에서 푸쉬를 한 후에 다른 쪽에서 푸쉬를 할 때의 상황이다. 먼저 푸쉬를 한 측이 origin의 마스터를 가지고 있다. 이 상태에서 함부로 다른 쪽에서 푸쉬를 하면 먼저 한 쪽의 마스터 브랜치의 작업 상황을 잃어버리는 상황이 나올 수 있기 때문에 깃 자체적으로 거부하는 것이다. 

이를 위해 git pull을 쓴다. 이 과정은 사실 fetch와 merge의 과정이 통합된 명령어이다. 일단 fetch는 다운을 받는다. origin에 있는 버전을 일단 가져와 준다. 그 후에 merge. 우리의 마스터와 머지한다!
결과적으로 원격과 로컬에서 온 것들이 융합된 새로운 버전이 생긴다.
이렇게 하면 원격 저장소에 있는 내용이 이미 받아들여진 상태에서 푸쉬를 하게 되므로 문제가 발생하지 않는다.

원격에서 온 right이란 커밋과, 내 로컬에 있던 work seven을 부모로 하는 새로운 버전이 생겼다. 이 상태에서 푸쉬하면 끝! pull 속에 fetch가 있다는 것을 처음 알아서 조금 충격적이다..!

피어세션

깃헙 특강이 있고 난 후의 피어세션이라 다들 다른 공부를 할 시간은 많이 없었다. 기본 과제를 푼 인원이 두어 명 정도 있었고, 일단 내가 한 풀이를 공유했다. 그렇지만 이 풀이도 완벽한 것은 아니라, 내일 피어세션 때 다들 풀어서 이야기하는 시간을 가지기로 했다.
이후로는 팀에 대한 토크를 계속 하다가 코테를 보았다. 25710번: 점수 계산 (acmicpc.net) 이게 문제였는데, 굉장히 단순해보이지만 시간 제한이 매우 빡빡해서 결국 실패했다. 나중에 들어보니 비둘기 집의 원리를 사용하는 문제라고 하는 것 같은데, 나는 어떻게 해야 할 지 감이 잡히지 않는다. 나는 일단 결국 배열 내에서 만들어질 수 있는 모든 숫자 조합을 고려해야 한다고 생각했는데 애초에 거기에서부터 시간초과가 나기 때문에 그것을 벗어난 풀이가 필요하다. 그 부분 이후 구현에 대해서는 시간을 단축시킬 방법이 있는 것 같아서 신나게 구현했는데, 막상 확인해보니 그것조차 벗어나질 못해서 결국 포기. 정렬을 하는 것도 소용이 없는 것 같고.. 뭔가 재밌어 보이는 문제인데 누구에게 도움을 요청해야 할지.

 

25710번: 점수 계산

길이가 N인 배열 a가 주어진다. 배열 a의 i번째 원소를 ai라고 정의하자. 다음 과정을 통해 배열에서 점수를 획득할 수 있다. 배열의 두 원소 ai, aj를 선택한다. (1 ≤ i < j ≤ N) 선택된 두 원소의

www.acmicpc.net

공부

깃헙 특강이 길게 있었던 지라 오늘도 개인 공부할 시간이 많이는 없었다. 그나마 다행인 건 이번 주 들어야 할 강의가 4개 뿐이라는 것. 깃 관련 공부를 한 것은 그래도 크게 만족이다. 모르는 내용들을 많이 알게 되었고, 과거에는 깃이 정말 내가 사용할 줄만 아는 것들이 몇 개만 있었는데 이제는 조금 더 잘 쓸 수 있을 것 같다. 

회고 및 다짐

나는 ML 엔지니어나 데이터를 다루는 일을 하고 싶다. MLops에 대해서 말만 들어보고 제대로 찾아본 적은 없는데 찾아보면 볼수록 내가 생각하는 길과 비슷한 종류의 일들을 가리키는 것 같다. 여기에 데이터를 다루는 각종 언어와 라이브러리들을 익히면 좋을 것 같다는 게 현재 나의 생각. 그렇다고 부캠에서의 공부를 서투르게 할 수는 없다. 여기에서 들을 수 있는 학습 경험은 여기에서만 들을 수 있다고 생각하고 기회를 놓치지 않아야겠다고 생각하고 있다. 아직 아는 게 많이 없을지라도, 내 눈이 틀리지 않았음을 믿고 나아가자.

일단 오늘 남은 강의를 다 들은 후에 내일부터 심화과제를 만지고 스터디 공부를 미리 시작할 계획이다. 스터디의 계획 상 우리는 NLP의 강의도 들어야 하기 때문에 미리 바쁘게 움직일 필요가 있다. 틈틈히 내 도메인 관련 정리도 진행해야 하는데 내일은 협업 필터링 정리를 조금 확실하게 하고 싶다. 내일도 스케줄이 조금 있어서 시간이 다 될 지는 미지수인데, 일단 해보자. 일 순위는 CF 정리, 그 다음 심화과제, 그 다음 NLP.