git과 github에 대해 공부한 점들을 기록합니다. 이 글은 git 공식문서와 wecode의 자료를 토대로 썼습니다.
Git의 공식 명칭은 분산 버전 관리 시스템 (VCS) 입니다. 쉽게 말해, 프로젝트 파일의 변경 사항을 추적하는 시스템입니다. 이를 통해 개발자들은 프로젝트의 변경 사항을 기록하고, 특정 시점의 버전으로 언제든 돌아갈 수 있습니다.
git은 버전을 관리하기 위해 파일들을 녹화한다는 느낌이라고 이해할 수 있다. 다른거 필요 없이, 1. 다른 사람들과 코드를 공유하고 생각을 주고받을 수 있다.
2. 한 프로젝트를 여러가지 버전으로 관리할 수 있다.
평행우주가 생각난다. 선택을 후회하는 일은 빈번하다. 그래서 항상 우리는 '아, 그 선택을 하지 않았더라면..'이라는 생각을 한다. git과 브랜치는 평행우주의 어디로든 갈 수 있게 해주는 타임머신과 같다.
Git으로 관리하는 프로젝트 저장소.
Git repository 에는 크게 두 가지 종류가 있습니다.
If you have a project directory that is currently not under version control and you want to start controlling it with Git, you first need to go to that project’s directory.
git init
This creates a new subdirectory named .git that contains all of your necessary repository files — a Git repository skeleton. At this point, nothing in your project is tracked yet.
프로젝트 해당 directory 안에서 git init
이라고 치는 순간, 해당 폴더 내에 숨겨진 .git 디렉토리를 생성한다. .git 디렉토리 안에는 git이 추적하는 모든 정보가 들어간다. 이제 git은 현재 저장소에 대한 모든 변경사항을 추적하기 시작한다. 한 마디로, local repository는 이미 생성한 셈이다. 그러나 아직은 아무 파일도 tracking되고 있지 않다.
주의 : git의 추적과 추적기록을 전부 없애려면 rm -rf .git
명령어를 치면 된다. 말 그대로 .git
폴더를 삭제하는 것.. 절대 해서는 안된다.
Git receives a full copy of nearly all data that the server has. Every version of every file for the history of the project is pulled down by default when you run git clone.
remote repository의 모든 파일, 코드들을 local repository로 다운로드받는다고 생각하면 된다. 그런데 신기한 점은, git의 모든 log들이 다 나온다는 것.
즉, git clone은 해당 remote repository의 모든 버전들까지 가져온다. 만약 내가 local repository로 만들던 파일들이 없어진다고 가정해보자. 그때 파일들만 없어지는게 아니라 git이 추적하던 모든 변경사항, 버전들까지 사라진다면 정말 큰 문제가 된다.
그래서 remote repository에서 해당 정보를 담고 있고, git clone
을 할 때에도 편의를 위해 버전까지 모두 가져오는 듯하다.
git status
it으로 작업 할 때 굉장히 자주 사용되는 명령어입니다. 어떤 파일이 변경되었는지, 어떤 파일이 추가되었는지 등을 전부 보여줍니다.
이름으로 예상할 수 있듯이 상태를 보는 명령어이다. 현재 git이 추적하는 파일들이 staging area에 있는지 없는지를 보여준다. commit을 남기려면 staging area로 추가해야 한다.
이 경우는 두 파일에 변경사항이 있지만, 아직 staging되지 않았다는 사실을 알려준다. 맨 밑에서는 이 변화들이 add
이 경우는 한 파일에 변경사항이 있지만, track되고 있지 않는다는 사실을 알려준다. 그리고 git add
명령어를 써서 commit될 수 있도록 하라고 설명도 해준다.
스테이징이란 뭔가? staging이 git의 평소 추적과 다른 점은 뭔가?
git add .
위의 명령어는 해당 디렉토리 내의 모든 파일과 디렉토리들을 git의 staging area에 추가시킨다. staging area에 들어가고 나면, commit이 되거나 아직 commit이 되지 않거나 둘 중 하나이다.
.
은 해당 디렉토리의 모든 변경사항을 staging area에 추가하겠다는 의미이다. 다른 경로 커맨드와 마찬가지로 특정파일.확장자
의 형식이나 *.확장자
로 특정 파일 혹은 특정 종류의 파일들만 staging시킬 수 있다.
Remember that each file in your working directory can be in one of two states: tracked or untracked. Tracked files are files that were in the last snapshot; they can be unmodified, modified, or staged. In short, tracked files are files that Git knows about.
As you edit files, Git sees them as modified, because you’ve changed them since your last commit. As you work, you selectively stage these modified files and then commit all those staged changes, and the cycle repeats.
git의 lifecycle. git add
를 하기 전에는 변경 사항이 working tree에서만 유효하다. git add
이후엔 해당 변경사항들이 stage에 올라가 있다. 그리고 git commit
을 하게 되면 git은 local repository에 기록하게 되고(하나의 버전이 되는 것), 해당 변경사항은 staging area에서 내려온다. 그리고 또 git add
를 하기 전에는 git이 변경되었다는 사실만 추적을 하고 있다. local repository에서 git의 사용은 이 과정의 반복이다.
The git add command takes a path name for either a file or a directory; if it’s a directory, the command adds all the files in that directory recursively.
git add
의 대상이 directory일 경우, 해당 directory안의 모든 파일 변경사항들을 staging하게 된다.
이미 git add
를 통해 staging된 파일이지만, 또 내용이 변경되었다면 해당 변경사항은 아직 staging된 게 아니다. 그래서 그 변경사항을 staging 적용시키려면 다시 git add
를 해줘야 한다.
It turns out that Git stages a file exactly as it is when you run the git add command. If you commit now, the version of CONTRIBUTING.md as it was when you last ran the git add command is how it will go into the commit, not the version of the file as it looks in your working directory when you run git commit. If you modify a file after you run git add, you have to run git add again to stage the latest version of the file.
git status -s
로 git status를 짧게 볼 수 있다.
New files that aren’t tracked have a
??
next to them, new files that have been added to the staging area have anA
, modified files have anM
and so on. There are two columns to the output — the left-hand column indicates the status of the staging area and the right-hand column indicates the status of the working tree.
??
는 working tree에는 존재하지만 git stage에 들어가지 않은, 그래서 아직 git이 변경사항을 추적하고 있지 않은 파일이다.
M
은 modified의 약자로, git stage에 있던 파일에 변경사항이 있었음을 뜻한다.
A
는 added의 약자로, working tree에 존재하던 파일(혹은 새로 생성된 파일)이 새롭게 git stage에 들어갔다는 뜻.
D
는 git이 추적하던 파일이 working tree에서 삭제되었다는 뜻.
설명하는 열이 두 줄인데, 왼쪽은 git의 staging area에서 일어나는 일들을 설명하는 줄이고 오른쪽은 working tree에서 일어나는 일들을 설명하는 줄이다.
README.md
파일은 이전에 변경사항들이 staging area에 들어갔지만 (commit되지 않음), working tree에서 새로운 변경사항이 생겼다.
README2.md
파일은 working tree에서는 변경사항이 생겼지만, 해당 변경사항들이 staged되지 않았다.
README3.md
파일은 파일 자체가 새로 staging area에 들어갔다.
a.md
파일은 원래는 staging area에 있었지만, working tree에서 삭제되었다는 걸 뜻한다. 그러나 아직 삭제되었다는 사항이 staging area에 들어오지 않았다.
you’ll probably use it most often to answer these two questions: What have you changed but not yet staged? And what have you staged that you are about to commit?
git diff
는 아직 staging area에 들어가지 않은, 즉 working tree에서 일어난 변경사항들만을 표시한다.
git diff --staged
는 staging area에 들어간 변경사항들만을 표시한다.
그리고 commit을 하는 순간, git diff
는 어떤 변경사항도 보여주지 않는다. 이미 버전화가 되었기 때문에, 더 이상 변경사항이 아니게 되기 때문이다.
많이 쓸 일은 없겠지만, git restore
을 사용하면 local repository에서 일어난 변경사항이 아직 commit이 된 상태가 아니라면, 이전 버전으로 되돌릴 수 있다.
만약 staging area에 올려놓은 상태라면 앞에 --staged
를 붙이면 staging area에서 해당 파일의 변경사항을 내릴 수 있다. 또한 아직 staging area에 있지 않은, working tree에서의 변경사항만 있는 상태라면 git restore
을 이용해서 working tree에서의 변경사항을 이전으로 되돌릴 수 있다.
.gitignore
은 하나의 파일이고, 설정파일에 가깝다. 설정 파일이나 부가적인 파일들처럼 local repository에서 매번 다루기 귀찮거나, 비밀번호처럼 민감한 정보를 담고 있는 파일의 경우 특정 파일 혹은 확장자를 숨길 수 있다.
Remember that anything that is still unstaged — any files you have created or modified that you haven’t run git add on since you edited them — won’t go into this commit.
commit은 staging area에 올라간 변경사항들에 대해서만 이루어진다. 즉, git add
로 staging area에 올려놓지 않은, working tree에서만 이뤄진 변경사항은 절대 commit에 포함되지 않는다.
git commit -m "Commit message"
커밋 후 :
Remember that the commit records the snapshot you set up in your staging area. Anything you didn’t stage is still sitting there modified. Every time you perform a commit, you’re recording a snapshot of your project that you can revert to or compare to later.
-a
: staging을 건너뛸 수 있다. 확신이 드는 변경사항이라면 이렇게 commit하는게 편할 듯.
이제는 track되지 않는 파일만 남아있다.
--amend
: commit 메세지를 바꿀 수 있다.
모든 commit history를 보려면 git log
. log는 각 커밋에 대한 자세한 정보를 담고 있습니다. (작성자, hash 값, 날짜와 시간, 그리고 커밋 메세지)
특정 commit 시점으로 돌아가고 싶다면 git checkout 해쉬
To be able to collaborate on any Git project, you need to know how to manage your remote repositories. Remote repositories are versions of your project that are hosted on the Internet or network somewhere.
git이 분산버전관리시스템이라면, github는 그런 git이 추적하는 버전들이 모이는 곳이라고 보면 된다.
GitHub을 사용하여 로컬 프로젝트 repository를 원격 클라우드 기반 GitHub 저장소에 업로드 할 수 있고, public repository 들을 통해 다른 개발자들과 교류할 수도 있습니다.
추가적으로 다른 사람들이 내 코드를 보고 내가 어떤 개발자인지 알 수 있게 할 수도 있고, 다른 개발자들과 연결하는 미디어로써도 기능이 좋기 때문에 깃허브는 필수다.
Common Workflow: 내 로컬 Repository를 GitHub 에 push 하기
git remote add origin 레퍼지토리주소
git push -u origin master
git remote add <shortname> <url>
: local repository와 remote repository를 연결짓는다. <shortname>
부분은 어떤 이름이든 될 수 있다. 기본적으로는 origin
이라는 이름으로 되어있다. 그러나 변수명처럼 바뀔 수 있고 여러 remote repository를 쓸 수 있기 때문에 여러 이름을 가질 수 있다.
git push <shortname> <branchname>
git fetch <remote>
The command goes out to that remote project and pulls down all the data from that remote project that you don’t have yet.
If your current branch is set up to track a remote branch, you can use the git pull command to automatically fetch and then merge that remote branch into your current branch.
Git doesn’t store data as a series of changesets or differences, but instead as a series of snapshots. When you make a commit, Git stores a commit object that contains a pointer to the snapshot of the content you staged. This object also contains the author’s name and email address, the message that you typed, and pointers to the commit or commits that directly came before this commit
브랜치란 독립적으로 어떤 작업을 진행하기 위한 개념입니다. 필요에 의해 만들어지는 각각의 브랜치는 다른 브랜치의 영향을 받지 않기 때문에, 여러 작업을 동시에 진행할 수 있습니다.
Branching means you diverge from the main line of development and continue to do work without messing with that main line.
blobs (each representing the contents of one of the three files), one tree that lists the contents of the directory and specifies which file names are stored as which blobs, and one commit with the pointer to that root tree and all the commit metadata.
각각의 commit은 snapshot(commit할 시점의 파일내용들, 즉 변경사항들)을 포인팅하고 있다고 이해하면 된다.
How does Git know what branch you’re currently on? It keeps a special pointer called HEAD.
HEAD는 branch중에서도 local에서 현재 자신이 있는 branch임을 뜻한다. 사진에선 지금 master branch에 있다.
git branch 새로운브랜치
What happens when you create a new branch? Well, doing so creates a new pointer for you to move around.
git checkout testing
branch를 생성하는 동시에 전환하고 싶다면 checkout 뒤에 -b
를 붙여준다.
만약 master이 아닌 다른 branch에서, master보다 앞서는 변경사항을 만든다면 어떻게 될까?
master branch의 파일내용 :
testing branch의 파일 내용 :
이 상황의 도식화 :
만약 git checkout master
을 한다면?
That command did two things. It moved the HEAD pointer back to point to the master branch, and it reverted the files in your working directory back to the snapshot that master points to. This also means the changes you make from this point forward will diverge from an older version of the project. It essentially rewinds the work you’ve done in your testing branch so you can go in a different direction. when you switch branches, Git resets your working directory to look like it did the last time you committed on that branch. It adds, removes, and modifies files automatically to make sure your working copy is what the branch looked like on your last commit to it.
HEAD는 master branch를 포인팅하게 된다. 즉, working tree의 모든 내용이 master branch의 내용으로 바뀌게 된다.
그럼 master에서 testing branch와 내용을 다르게 만든다면?
어떤 제품에 대한 테스트를 하고 싶다면, 원래 쓰던 branch를 모두 바꾸는 것 보다는, 기존의 유지할 부분은 유지하되 새로운 branch에서 작업하는 쪽이 안전할 것이다.
git merge <branchname>
이제 전체 branch의 모양새는 다음과 같다 :
여러 branch의 변경사항을 한 branch로 병합할 수 있다. git은 branch들의 공통되는 조상을 찾은 다음, 다른 변경사항들을 짜집기해서 병합시킨다.
주의 : 서로 같은 파일 혹은 디렉토리에 다른 변경사항이 있다면, merge시 충돌이 일어난다. 따라서 최소한 한 쪽에는 변화가 없는 (중점으로 두려는 파일에 대해서) 상태에서 병합을 진행해야 한다.
테스팅용 branch에서 테스트가 끝나고 merge가 끝났다면, 해당 branch를 삭제해주면 된다.
git branch -d 브랜치
Occasionally, this process doesn’t go smoothly. If you changed the same part of the same file differently in the two branches you’re merging, Git won’t be able to merge them cleanly.
Git hasn’t automatically created a new merge commit. It has paused the process while you resolve the conflict.
git clone 레포지토리링크
: 해당 경로에 레포지토리의 모든 파일들을 받을 수 있다.
master 브랜치를 건드릴 필요없이 작업환경에서 기능을 추가하거나 테스트를 진행할 수 있게 되는것이죠. 나중에 전부 완료가 된다면, 그 때 master 브랜치와 merge (병합) 해줄 수 있습니다.
커스텀 브랜치를 push 하고 master 브랜치에 적용될 준비가 되었다면, Pull Request (PR) 라는 것을 통해 프로젝트 오너 (혹은 팀 리더) 에게 내가 작업한 브랜치의 작업내용을 master 브랜치에 반영해달라는 요청을 보낼 수 있습니다.
새로운 아이디어가 떠올라서 기존의 코드를 바꾸려는데, master을 건드리자니 위험하다 싶을 때가 있을거다. 그럴 때 새로운 branch를 만드는 거다. 기존의 master branch 코드를 가져오되, 다른 branch에서 작업을 하면 위험한 일이 생길 걱정이 없다.
커스텀 브랜치를 push 하고 master 브랜치에 적용될 준비가 되었다면, Pull Request (PR) 라는 것을 통해 프로젝트 오너 (혹은 팀 리더) 에게 내가 작업한 브랜치의 작업내용을 master 브랜치에 반영해달라는 요청을 보낼 수 있습니다.
커스텀 브랜치를 push 하고 master 브랜치에 적용될 준비가 되었다면, Pull Request (PR) 라는 것을 통해 프로젝트 오너 (혹은 팀 리더) 에게 내가 작업한 브랜치의 작업내용을 master 브랜치에 반영해달라는 요청을 보낼 수 있습니다.
git checkout
은 branch에서도 쓰이던데, branch와 hash(git의 시점)이 결국 같은개념인건가?