6. ls - /d/Testdir/base 폴더 내 정보들을 표기합니다. [clone한 폴더 확인]
7. cd Git-Description-Repository/ - base폴더 안에 폴더 이동
(main)이 뜬다면 현재 .git이 있는 폴더에 들어온 것이고, 현재 위치는 main 브랜치이란 뜻입니다.
그리고 깃주소를 가져올 때, Ctrl+v가 잘안될 것입니다. Ctrl+Insert로 붙여넣기를 해주세요.
한번 수정 사항을 이제 수정사항을 만들어볼까요?
git status - 현재 수정된 사항들 리스트업
git add 파일명 - 해당 파일을 Stage에 올리기
git commit - Stage에 올릴 것들을 확정하고, 무엇을 올리는지 설명하는 구간
📝 Git 커밋 시 나오는 창 설명 (vim 기준)
Git에서 커밋을 하면 vim 편집기 창이 열립니다.
i 키를 누르면 → Insert 모드로 전환되어 → 커밋 메시지를 입력할 수 있습니다. (이때 입력하는 글씨가 보통 노란색으로 보입니다) 커밋 메시지를 모두 작성했다면 → Esc 키를 눌러 → 입력 모드(Insert)를 종료합니다. :wq 명령어를 입력합니다. → Write(저장) Quit(종료) 커밋이 완료됩니다.
git status - 커밋이 정상적으로 잘 들어온 것을 확인
git push - 해당 내용을 원격 저장소에 올리기
Png와 README 수정된 내용들이 잘 올라왔습니다.
그러면 이제 의도적으로 Conflict(충돌)가 나오게 한번 수정해볼까요?
하지만, git bash로 일일히 타이핑해가며 작업하는건 너무 불편합니다.
CLI로 Git을 다루는건 어느정도 익히셨을테니, 이제는 GUI인 Fork로 작업을 시작하겠습니다.
File - Open Repository[Ctrl+O]
.git이 나오는 폴더 구간이 나오는 폴더에서 폴더 선택을 눌러주시면 됩니다.
여기서 핵심적인 개념들을 다루겠습니다.
Git의 고양이 마크 - 해당 브랜치가 원격 레파지토리에서의 최신화된 영역을 의미합니다.
✅ - 현재 내 시점을 의미합니다.
상단의 밑줄 - 현재 브랜치의 헤드(위치)를 의미합니다.
해당 로그를 우클릭하면 해당 로그의 시점에서 new Branch를 통해 브랜치를 나눌 수 있습니다.
체크박스 ☐
브랜치만 생성하기
체크박스 ☑
브랜치를 생성한 후, 브랜치 헤드를 해당 위치로 이동하기
현재 상황을 정리하겠습니다.
Readme 수정이라는 로그가 있습니다.
해당 로그를 기준으로 userA, userB, Main이라는 브랜치가 생성되었고
userB에 ✅가 있으므로 현재 위치는 userB이며, Readme 수정이라는 사실을 알 수 있습니다.
일단 userA로 헤드를 바꾸고[Checkout], 수정작업을 먼저 진행해보겠습니다.
깃의 헤드를 바꿀려면 여러방법이 존재하는데, 두 그림의 방식으로 추천드립니다.
왼쪽 탭을 활용해 헤드를 바꾸는 방식은 최신 헤드로 이동하는 방식입니다.
현재 기존과 다른 피카츄 이미지를 2장을 넣고, 하나는 기존과 이름을 같게해서 파일의 수정사항을 만든 상황입니다.
왼쪽탭에 Local Chage에 변경사항이 생겼으니 클릭해서 들어가면 위와 같이 창이 변경됩니다.
Stage 버튼을 통해서 Unstatged에서 Stage로 옮깁니다.
Stage로 올리고싶지 않은 파일은 날리면 됩니다.
Delete 키를 통해서 해당 파일을 날릴 수도 있습니다. 폴더에서 아예 지우는 것이니 조심히 사용하길 바랍니다.
Commit로그를 작성해 로그명을 정해주시고, Commit버튼을 통해 Commit을 해주세요.
userA라는 커밋 로그가 생겼지만, 고양이 마크가 없으니 아직 저기까진 깃에 올라간상태가아닙니다.
이제 Push를 때려볼까요?
보통은 이대로 Push를 때리는걸 추천드립니다.
깃 고양이 마크가 생겼네요. 이제 해당 로그 영역이 제일 최신화된 영역입니다.
자 이제 userB 브랜치로 checkout해서 작업을 진행해볼까요?
userA에서 피카츄 이미지2개가 있지만, userB는 1개이며,
Pokémon_Pikachu_art.png라는 파일이 서로 다르게 나오고 있습니다.
userA의 작업내역이 userB하고는 완전히 분리된 것을 확인했습니다.
Pokémon_Pikachu_art.png 파일을 변경하고, Commit하고 Push하겠습니다.
그럼지금까지의 작업내역을 한번 정리하겠습니다.
현재 각 브랜치별로 서로 다른 피카츄 PNG파일들이 있는 모습입니다.
이제 작업한 내역들을 main에 올리는 작업을 진행하겠습니다. 먼저 userA부터 넣겠습니다.
Merge는 현재 HEAD에 다른 브랜치의 작업내역을 끌어오는 행위를 말합니다.
즉 Main 브랜치에서 userA의 작업 내역을 Merge를 해야합니다.
그대로 Merge를 진행해주시면됩니다.
Merge를 하면 꼭 Push를 진행해야합니다.
그림을 보면 main의 commit된 것같은 내역이 남아있습니다.
push한 후 모습으로 깃 고양이가 main 브랜치의 최신을 잘보여주네요.
main 브랜치가 userA와 파일구조가 같게 된 것을 확인했습니다.
자 이제 userB도 Main쪽으로 Merge해볼까요?
Conflict(충돌)가 생겼습니다. 왜 생겼는지 확인해볼까요?
현재 Pokémon_Pikachu_art.png파일이 작업내역이 겹쳐서 생긴 이슈가 발생된것으로 파악됩니다.
저는 userB를 선택해서 main브랜치 안에 userB의 거대 피카츄 이미지를 넣겠습니다.
그렇다면 보내는 과정에서 이슈가 생기는 경우와 역으로 어떻게 받는가?에 대해서 다룰 예정입니당.
Push를 할 때, 우리는 수정된 작업 내용을 올리는 행위를 하게됩니다.
근데 언제 작업시점을 기준으로 언제 작업내역을 수정을 완료했는가?에서 예외적인 상황이 생기게 됩니다.
그림적으로 보면 A와 B 두 명의 작업자가 있습니다.
① 시점 1 - A와 B는 같은 시점(시점 1) 의 작업물을 기준으로 각각 로컬에서 수정을 시작합니다.
② 시점 2 – A의 Push - A가 먼저 작업을 끝내고 Push를 진행합니다. - 이로 인해 원격 저장소는 시점 2가 되며, A의 수정 사항이 정상적으로 반영됩니다.
③ 시점 3 - B의 Push 시도 - B는 여전히 시점 1 기준으로 작업을 진행한 상태입니다. - 이 상태에서 B가 Push를 시도하면, 이미 누군가(A)가 작업을 진행했기 때문에 Push가 거부됩니다.
④ Pull을 통한 최신화 - B가 Push를 하려면 먼저 Pull을 해서 원격 저장소의 최신 상태(시점 2)를 받아와야 합니다. - 이 과정에서: = B가 수정하지 않았던 A의 변경 내역이 B의 로컬 작업 내역에 합쳐집니다. = 하지만 같은 파일의 같은 부분을 수정한 경우, 충돌(Conflict) 이 발생합니다.
⑤ Conflict 발생 - 이 시점에서 Git은 A의 작업물과 B의 작업물 중 어떤 것을 기준으로 할지, 사용자가 직접 선택하도록 요구합니다. - 이 상황을 Conflict(충돌) 라고 합니다.
⑥ Conflict 해결 방식 - 보통은 작업자끼리 협의하여 어떤 수정 사항을 살릴지 결정합니다. - 하지만 저는 보통: = 제 작업을 날리는 방식을 선택합니다. 협의 과정이 필요 없고, = Push 전에 충돌이 날 것을 미리 예측해 해당 부분에 예비 파일을 만들어 둡니다. = 이후 Pull → Push를 한 다음, 다시 필요한 수정을 진행하여 재차 Push하는 방식을 선호합니다.
보통 협업 시에는 Dev 혹은 Main 브랜치를 작업의 기준이 되는 중심 축으로 둡니다.
이 기준 브랜치는 항상 정상적으로 동작해야 하며, 빌드 및 테스트가 가능한 안정적인 상태를 유지하는 것이 목적입니다.
이 기준 브랜치에서 추가적인 기능을 개발하거나, 기존 로직을 수정하는 작업들은 메인 흐름에서 바로 진행하기보다는 곁가지, 즉 Branch로 분리하여 관리합니다.
이렇게 Branch를 새로 생성해 작업을 분리하면, 작업 내용을 격리(Isolation) 할 수 있고, 기준 브랜치를 망가뜨리지 않으면서, 변경 사항을 관리 가능한 단위로 유지할 수 있습니다.
Branch를 나누는 장점
Branch를 나누어 작업할 경우, 다음과 같은 장점이 있습니다.
1. 작업 격리 (Isolation) 각 작업을 별도의 브랜치에서 진행함으로써, 미완성 기능이나 실험적인 수정이 기준 브랜치에 직접적인 영향을 주지 않도록 할 수 있습니다.
작업 중 문제가 발생하더라도 해당 브랜치만 정리하거나 삭제하면 되기 때문에 리스크를 최소화할 수 있습니다.
2. 안정성 유지 (Stability) main 또는 dev 브랜치는 항상 안정적인 상태를 유지하는 것이 중요합니다.
브랜치를 통해 작업을 분리하면, 개발 중인 코드로 인해 기준 브랜치가 깨지는 상황을 방지할 수 있으며, QA, 테스트, 배포 기준점으로 활용하기에도 적합합니다.
3. 리뷰 & 협업 (Review) 브랜치 단위로 작업하면 Pull Request를 통해 변경 내용을 명확히 확인할 수 있습니다. - 어떤 파일이 수정되었는지 - 왜 이런 변경이 필요한지 - 충돌 가능성은 없는지 를 사전에 공유하고 검토할 수 있어 협업 품질이 향상됩니다.
4. 작업 단위 관리 (Feature 단위) 기능, 이슈, 작업 티켓 단위로 브랜치를 나누면 변경 사항의 범위가 명확해집니다.
이로 인해: - 특정 기능만 선택적으로 병합 - 문제 발생 시 해당 작업만 롤백 과 같은 관리가 수월해집니다.
5. 병렬 작업 (Parallel Work) 여러 작업자가 동시에 서로 다른 브랜치에서 작업할 수 있어, 작업 간 간섭을 최소화할 수 있습니다.
예를 들어: - 한쪽에서는 신규 기능 개발 - 다른 한쪽에서는 버그 수정 - 또 다른 한쪽에서는 최적화 작업 을 동시에 진행할 수 있어 전체 개발 속도가 향상됩니다.
6. 배포 전략 (Release / Hotfix) 브랜치를 활용하면 배포 흐름을 명확하게 분리할 수 있습니다. - release 브랜치: 배포 직전 안정화 작업 - hotfix 브랜치: 운영 중 발생한 긴급 수정 을 통해 운영 버전과 개발 중인 버전을 분리 관리할 수 있으며, 예기치 않은 문제에도 빠르게 대응할 수 있습니다.
정리하면
Branch는 단순히 컨플릭트를 줄이기 위한 수단이 아니라, 작업을 안전하게 분리하고, 협업과 관리, 배포까지 고려한 개발 흐름을 구조화하는 도구라고 볼 수 있습니다.
이제 우리는 작업물을 수정해서 올리는 방법과 작업구역을 어떻게 관리하는가? 에 대해 잘 알고 있습니다.