-
[Git] Command 알아보기저장소/git 2019. 12. 7. 17:59
지금까지 gitlab이나 github을 사용할 때, 커맨드를 쓰지 않고 source tree에서 제공하는 GUI로 처리했습니다. GUI가 편리하긴 하지만, 프로젝트의 크기가 커지고 브랜치가 많아지는 경우 살짝 느려지는 경향이 있습니다. 이를 보완하고 git 커맨드에 친숙해지고자 커맨드를 사용하는 방법을 설명합니다.
git 저장소 생성
기존 폴더를 git 저장소로 추가
$ git init Initialized empty Git repository in /.../test_git/.git/
test_git이라는 폴더를 저장소로 git 저장소로 추가한 방법입니다. 해당 폴더에 들어간 후, $ls -la | grep .git을 하면 .git 파일이 추가된 것을 확인할 수 있습니다. 로컬에서 .git을 추가한 것이므로 파일을 추가, 커밋, 푸쉬까지 이뤄져야 서버에도 반영이 됩니다. 해당 내용은 아래에서 천천히 설명합니다.
서버에 있는 저장소를 clone
gitlab이나 github에 있는 저장소를 로컬에 추가하고 싶을 때 사용합니다.
$ git clone https://github.com/brownbears1/test.git Cloning into 'test'... remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), done.
test라는 프로젝트를 로컬에 내려받습니다. 이 때, 프로젝트명인 test라는 폴더에 생성이 됩니다. 만약 폴더명을 임의로 추가하고 싶으면 아래와 같이 지정하면 됩니다.
$ git clone https://github.com/brownbears1/test.git custom_test
파일 추가/수정 후 저장
위 test 프로젝트를 내려받았다면 자동으로 checkout이 된 상태입니다. 여기서 파일을 추가하고 수정한 다음, 해당 서버에 올리는 동작을 설명합니다.
tracked/untracked 이해하기
git에서 모든 파일은 tracked 와 untracked 상태로 나눌 수 있습니다.
tracked 상태는 스냅샷에 포함된 파일이고 unmodified(변경된 사항 없음), modified(변경됨), staged(커밋으로 저장소에 기록) 상태로 또 나눌 수 있습니다.
이외의 파일들은 untracked 상태이며 해당 상태의 파일들은 스냅샷에 포함된 것이 아니고 stage 대상도 아닙니다.
여기서 스냅샷의 의미는 git 저장소에 해당 파일이 있는지의 유무입니다. 스냅샷에 포함된 파일이라 하면, git 저장소에 존재하는 파일입니다.
unmodified 상태면 변경된 사항이 없는 상태이고
modified 상태면 git에 존재하는 파일의 내용을 수정한 상태이고 (이 상태는 배포 준비가 되지 않음)
staging은 modified의 상태에서 배포를 하겠다 라고 stage에 추가한 상태입니다. (배포시, 서버에 적용)
파일의 추가/수정 추적하기
프로젝트 내에 README.md 파일이 있어서 해당 내용을 수정한다고 가정합니다. 이후, 파일을 추적하기 전에 상태값을 확인하도록 합니다.
$ git status On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: README.md no changes added to commit (use "git add" and/or "git commit -a")
여기서 git status는 변경/추가된 파일들을 보여줍니다. 위 상태는 README.md 파일에 변경이 있지만 아직 stage에 올라가지 않은 상태입니다. stage에 올리도록 아래와 같이 add를 한 후, 다시 status로 확인합니다.
$ git add README.md $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md
Changes to be committed 문구와 같이 stage 상태로 올라간 것을 확인할 수 있습니다.
이번에는 새로운 파일인 test.txt를 만들고 위와 같이 똑같은 절차를 진행합니다.
$ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md Untracked files: (use "git add <file>..." to include in what will be committed) test.txt $ git add test.txt $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md new file: test.txt
만약 위 stage 상태를 만든 다음, test.txt를 수정하게 된다면 파일의 상태가 unstage 상태로 됩니다. 이때, 수정한 내용은 커밋에 반영이 안되므로 다시 git add를 해야 합니다.
만약 생성/변경한 모든 파일을 stage로 추가하고 싶으면 아래와 같이 .을 사용합니다.
$ git add .
변경사항 커밋하기
위에서 설명한 것과 같이 stage 상태인 내용들을 커밋하도록 합니다.
$ git commit -m '커밋 테스트' [master 457f83a] 커밋 테스트 2 files changed, 2 insertions(+) create mode 100644 test.txt
여기서 커밋은 변경사항을 현재 내 컴퓨터에 저장하는 것이고 원격 저장소에는 반영이 되지 않은 상태입니다. -m '커밋 테스트' 에는 커밋 메시지를 작성하도록 합니다.
만약 git add 이후 stage 상태인 파일을 또 수정하게 된다면 다시 add를 해줘야 합니다. 이러한 번거로움을 덜고자 아래와 같이 사용하여 tracked 상태의 파일들이 변경사항이 있을 때, 자동으로 stage 상태로 추가하고 커밋하도록 할 수 있습니다.
$ git commit -am '커밋 테스트'
stage된 파일 제거하기
commit까지 이룬 상황에서 부득이하게 서버에 반영을 하지 않고자 하면 해당 파일을 제거해야 합니다.
$ git rm test.txt $ ll README.md
위 명령어만 입력하면 stage 상태에서 제거되는 것 뿐만 아니라 실제 파일도 지워지게 됩니다. 아래 옵션을 사용하여 파일은 그대로 두되, git이 추적만 하지 않도록 진행할 수 있습니다.
$ git rm --cached README.md rm 'README.md' $ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: README.md Untracked files: (use "git add <file>..." to include in what will be committed) README.md
커밋된 내용 서버에 반영하기
커밋된 내용을 push 명령어를 사용해 원격 저장소에 반영할 수 있습니다.
$ push -u origin master Counting objects: 3, done. Writing objects: 100% (3/3), 265 bytes | 265.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To https://github.com/brownbears1/test.git e4c4c0f..6acb1a3 master -> master Branch 'master' set up to track remote branch 'master' from 'origin'.
여기서 origin은 원격 저장소의 이름이고 master는 브랜치 이름입니다. clone을 하면 보통 원격 저장소의 이름이 origin으로 지정됩니다. -u 옵션은 원격 저장소에서 업데이트를 받은 다음, push를 하는 의미입니다.
이 옵션을 사용하는 이유는 해당 프로젝트를 복제한 사람들이 여러 명 있을 때, 다른 사람이 먼저 push를 하면 그 다음 사람들은 push를 할 수 없기 때문에 -u 옵션을 사용하여 최신 내용을 내려받아 머지한 다음, push를 해야 합니다.
이러한 이유 때문에 -u를 사용하지만 push를 하기 전, 프로젝트의 최신 내용을 먼저 pull 받은 다음 진행하는 것이 좋습니다.
만약 master에 반영하는 것이 아닌, 다른 브랜치에 반영을 하려면 master 대신 다른 브랜치의 이름을 지정하면 됩니다.
여기까지는 기존에 존재하는 원격 저장소를 복제한 다음 진행한 방법이고 새로운 폴더를 git 저장소로 추가한 경우 아래와 같이 원격 저장소의 주소를 추가해야 push가 가능합니다.
$ git remote add origin (원격 저장소 주소)
내용 되돌리기
모든 단계에서 생성/변경 한 파일을 되돌릴 수 있습니다. 여기서 주의할 점은 한 번 되돌린 내용은 다시 복구할 수가 없습니다.
commit 되돌리기
이미 커밋이 된 상태에서 커밋 메세지를 변경하거나, 다른 파일도 추가하여 커밋을 하고 싶을 때 사용할 수 있습니다.
$ git commit --amend -m '메시지'
만약 커밋을 한 다음, 다른 파일을 생성/추가가 안된 상태에서 위 명령어를 입력한다면 커밋 메시지만 변경한다는 의미입니다.
unstage로 되돌리기
git add . 으로 모든 파일이 stage 상태가 되었는데 특정 파일을 unstage로 바꾼다고 할 때, 아래와 같이 사용할 수 있습니다.
$ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md modified: test.txt $ git reset HEAD test.txt Unstaged changes after reset: M test.txt $ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: test.txt
modified 상태 파일 원복하기
기존에 존재하는 파일을 수정했다가 최근 원격 저장소에서 내려 받은 파일로 원복하는 방법은 아래와 같습니다.
git checkout -- README.md
이 방법으로 초기 파일 상태로 돌릴 수 있지만, 수정한 파일 위에 덮어쓰이는 방법 때문에 수정한 이력이 날라가 다시 복원을 할 수 없습니다.원격 저장소에서 최신 내용 내려받기
만약 누군가가 master에 내용을 변경해서 푸쉬를 했다면, 현재 내 로컬 저장소의 master와 내용이 다릅니다. 이를 맞춰주기 위해 원격 저장소의 브랜치를 내려 받아 로컬 저장소에 합칩니다.
$ git pull
pull 명령을 사용하면 원격 저장소의 변경 내용이 로컬에 받아지고(fetch), 이를 합칩니다. (merge)
충돌 관리하기
충돌은 같은 파일을 여러 사람이 수정한 다음, 한 명이 push하고 다음 사람이 push할 때 일어날 수 있거나 pull을 받을 때 발생할 수도 있습니다.
만약 충돌이 났다면 아래와 같은 메시지를 확인할 수 있습니다.
First, rewinding head to replay your work on top of it... Applying: 더 보기 버튼 추가 Using index info to reconstruct a base tree... M index.html Falling back to patching base and 3-way merge... Auto-merging index.html CONFLICT (content): Merge conflict in index.html Failed to merge in the changes. Patch failed at 0001 더 보기 버튼 추가 The copy of the patch that failed is found in: /path/to/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --continue". If you prefer to skip this patch, run "git rebase --skip" instead. To check out the original branch and stop rebasing, run "git rebase --abort".
여기서 핵심은 아래 3줄입니다. 충돌 문제를 해결했으면 git rebase --continue , 해당 파일을 건너뛰려면 git rebase --skip , 중단하려면 git rebase --abort 의 명령어를 용도에 맞게 사용하면 됩니다.
충돌한 파일을 열어보면 아래와 같이 구성되어 있습니다.
<<<<<<< HEAD <div> <p> 내가 수정한 내용 </p> </div> ======= <div> <p> 현재 원격 저장소에 누군가 올린 내용 </p> </div> >>>>>>>
<<<< HEAD 부터 ===== 까지가 내가 수정한 내용이고 ==== 부터 >>>>까지 누군가가 수정한 내용입니다. 이 부분은 사용자가 잘 판단하여 아래와 같이 정상적인 파일로 만들어 줍니다.
<div> <p> 내가 수정한 내용 </p> </div>
충돌 해결을 했으면 서버에 반영해야 하므로 아래와 같이 명령을 진행합니다.
$ git add index.html $ git rebase --continue