[IntelliJ / Git] branch / reflog / log

Dev.Hammy·2023년 11월 8일
0

Etc

목록 보기
8/20

IntelliJ에 프로젝트 생성


백준 온라인 저지 시스템의 코드와 리팩토링 과정, 공부 내용을 깃헙에 업로드 하기 위해 새로운 프로젝트를 생성하고 VCS로 Git을 지정했다. src 패키지 아래 알고리즘 분류 또는 단계별 분류로 패키지를 생성하고 그 하부에 각 문제별 패키지를 생성하여 README.md 에는 문제와 테스트 케이스를 기재하고 코드별 클래스 파일을 담았다. src 패키지에서 초록 글씨로 표시되는 부분은 현재 git에서 추적하고 있는 파일이고 빨간 글씨로 표시되는 부분은 추적하지 않는 파일이다.

# 현재 git이 추적하고 있는 파일 목록
git ls-files

# 출력 내용 : 위 스크린샷과 같다.
Dev-Hammy@treadmill:~/IdeaProjects/baekjoon$ git ls-files
.gitignore
.idea/.gitignore
.idea/misc.xml
.idea/modules.xml
.idea/uiDesigner.xml
.idea/vcs.xml
baekjoon.iml
src/DynamicProgramming/P_1463/P_1463.java
src/DynamicProgramming/P_1463/README.md

윈도우 상단에는 현재 브랜치의 위치가 'P_2839'로 나타난다. git branch 로 확인하면 현재 위치한 브랜치 이름 앞에 * 표시가 나타난다.

# 현재 사용 중인 브랜치
git branch

# 출력 내용 : 현재 위치한 브랜치 이름 앞에 * 표시
Dev-Hammy@treadmill:~/IdeaProjects/baekjoon$ git branch
  DynamicProgramming
  P_1463
* P_2839
  main

인텔리제이 윈도우 하단에는 Git 전용 패널도 존재한다. Log 패널에서 Branch 등을 확인할 수 있고 Console에서 실행내역을 확인할 수 있다.

Git 브랜치 생성 및 브랜치와 HEAD 위치 확인

# 모든 브랜치 확인
git branch -a
# 새 브랜치 생성하고 그 브랜치로 전환
git checkout -b <브랜치 이름>

로컬 디렉토리 구조를 따라서 git checkout -b DynamicProgramming으로 부모 브랜치를 생성한 다음, 자식 브랜치로 P_2839, P_1436을 생성하려고 한다. git checkout -b P_2839로 자식 브랜치를 생성한다.

p_1436은 하단의 Git Log 패널에서 DynamicProgramming 브랜치를 선택 후 마우스 우측 버튼을 클릭하여 New Branch from DynamicProgramming으로 생성하였다.

git reflog show --all | head -n 1

# 출력 내용
3e129d6 refs/heads/P_1463@{0}: branch: Created from DynamicProgramming^0
  • git reflog: git reflog 명령어는 HEAD 위치의 변경 내역을 보여줍니다.

  • show: git reflog 명령어에 사용되는 옵션으로, reflog 항목을 표시합니다.

  • --all: show 옵션과 함께 사용되며, 모든 reflog 항목을 표시합니다.

  • |: 파이프라인(pipe) 기호로, 왼쪽 명령어의 출력을 오른쪽 명령어의 입력으로 전달합니다.

  • head -n 1: head 명령어는 텍스트 데이터의 처음 몇 줄을 보여주는 명령어입니다. -n 1은 처음 1줄만 표시하라는 옵션입니다. 따라서 이 부분은 reflog의 처음 1개 항목만 표시하라는 의미입니다.

git reflog show --all | head -n 1 명령의 출력 결과에 따르면 현재 헤드가 위치한 브랜치는 P_1436이며 이 브랜치는 DynamicProgramming 브랜치로부터 생성되었다.

https://copyprogramming.com/howto/how-to-get-git-parent-branch-name-from-current-branch

# 현재 HEAD 위치를 확인
git symbolic-ref --short HEAD

# 현재 HEAD 위치가 위치한 브랜치를 확인
# 만약 HEAD가 직접 커밋을 가리키고 있다면, "HEAD detached at"과 함께 현재 커밋의 해시값이 표시됩니다.
git rev-parse --abbrev-ref HEAD

# 현재 위치한 브랜치의 부모 자식 관계를 확인
git show-branch --current

챗 지피티 말로는 ! 표시된 것들은 모두 현재 브랜치의 상위 브랜치라고 한다. rebase를 위해 사전 작업을 진행한다.

스테이징 영역 관리

git status

git status 명령은 현재 브랜치, 스테이징 영역, 작업 디렉토리의 변경 사항을 보여줍니다. 스테이징되지 않은 변경 사항은 "변경됨" 또는 "추적되지 않음"으로 표시됩니다.

패키지 별로 작업 내용도 분리하고 싶기 때문에 git restore --staged <file> 명령을 사용한다.

# 현재 브랜치에 staged 된 작업 내역 삭제 
git restore --staged <file>

# 새로 생성한 파일은 제외하고 수정/삭제한 내역만 추가
git add -u

# 프롬프트를 띄워 add 할 내용 선택하기
git add -p

commit, rebase, merge, cherry-pick

git commit

# commit 메시지를 편집할 수 있는 편집기가 나타나고 그 내용을 저장하면 아래와 같이 맨 첫줄의 내용이 보입니다.
[P_2839 573de30] [feat] (DynammicProgramming/P_2839) Implement Package
 3 files changed, 69 insertions(+), 71 deletions(-)
 create mode 100644 src/DynamicProgramming/P_2839/P_2839_1.java
 create mode 100644 src/DynamicProgramming/P_2839/README.md
 delete mode 100644 src/by_Type_DynmaicProgramming/P_2839.java

# DynamicProgramming 브랜치에 리베이스 
git rebase DynamicProgramming

위 스크린샷은 현재 브랜치가 P_2839일 때 아래 스크린샷은 현재 브랜치가 DynamicProgramming일 때이다.

git checkout <변경사항 커밋이 완료된 하위 브랜치의 상위 브랜치>
git merge <상위 브랜치에 붙일 하위 브랜치>

P_2839 브랜치의 내용이 DynamicProgramming 브랜치에 merge되어 같은 구조를 가지게 됐다.

P_1436 브랜치는 DynamicProgramming 브랜치로부터 created 되었지만, 변경사항이 자동으로 반영되지는 않았다. git add <파일경로지정>로 DynamicProgramming/P_1463 내부의 파일을 모두 stage 영역에 추가한다. git commit 을 실행하여 커밋 메시지를 작성 및 저장하고 git log로 현재 브랜치의 커밋 내역을 확인한다.

# 현재 브랜치 커밋 내역 확인
git log

# q 를 누르면 밖으로 나가짐

P_2839의 커밋 메시지에서 스코프를 표시했듯이 P_1436의 커밋메시지를 수정하려고 한다. git commit --amend 명령으로 수정한 커밋은 이전 커밋과 다른 SHA-1 해시 값을 가지므로 주의가 필요하다. 수정된 커밋은 이미 리모트 저장소로 푸시한 경우에는 사용하지 않는 것이 좋다.

# 기존 커밋 메시지 내용 수정

git commit --amend

커밋 메시지가 수정되면서 c0674 로 시작하던 마지막 커밋의 해시코드가 6a876으로 시작하는 해시코드로 변경되었다.


P1436 브랜치에는 'by_Type'으로 시작하는 패키지가 추적목록에 올라와 있었는데 이것을 제외한 나머지 커밋들만 반영하고 싶어서 git cherry-pick을 사용했다.

# 다른 브랜치의 커밋 목록을 보고 싶다면
git log <다른 브랜치 이름>

# 현재 브랜치에 추가하고자 하는 커밋의 해시코드를 이용
git cherry-pick <커밋 해시코드>

의도한 대로 작업이 수행되었다.

rebase, merge, cherry-pick의 차이

  • Merge: 브랜치를 병합할 때, 새로운 Merge 커밋이 생성되고 브랜치의 커밋 히스토리가 유지됩니다.
# merge 실행 전
--- A --- B --- C (feature-branch)
             \
              D --- E (main)
              
# merge 실행 후
--- A --- B --- C --- F (feature-branch)
             \       /
              D --- E (main)
  • Rebase: 커밋을 재배열하여 히스토리가 선형적으로 변합니다. 기존 커밋들은 새로운 부모 커밋 위에 재배열되어 합쳐집니다.
# rebase 실행 전
--- A --- B --- C (feature-branch)
             \
              D --- E (main)
              
# rebase 실행 후
--- A --- D --- E --- B --- C (feature-branch)
                        /
                     (main)
  • Cherry-Pick: 특정 커밋을 선택하여 현재 브랜치에 적용하며, 새로운 커밋(내용은 같지만 SHA 원본과 해시가 다름)으로 생성됩니다.
# cherry-pick 실행 전
--- A --- B --- C (main)
             \
              D (feature-branch)
              
# cherry-pick 실행 후
--- A --- B --- C --- D' (main)

브랜치, 커밋, 태그, HEAD 사이의 관계

  1. 커밋 (Commit):
  • 커밋은 Git 저장소에서 파일 및 디렉토리 변경 사항의 스냅샷을 나타냅니다.
  • 각 커밋은 이전 커밋의 상태를 기반으로 생성됩니다.
  • 커밋은 고유한 해시(일련 번호)로 식별됩니다.
  1. 브랜치 (Branch):
  • 브랜치는 커밋의 가리키는 참조입니다. 특정 커밋을 가리키는 포인터 역할을 합니다.
  • 브랜치를 만들면 현재 브랜치의 상태가 복사되어 새로운 브랜치가 생성됩니다.
  • 브랜치는 커밋의 이력을 추적하며, 새 커밋이 생성될 때 해당 브랜치가 가리키는 커밋이 업데이트됩니다.
  1. 태그 (Tag):
  • 태그는 커밋에 대한 고정된 참조(레이블)를 제공합니다. 특정 커밋을 의미있는 이름으로 표시할 때 사용됩니다.
  • 태그는 고정된 참조로, 특정 커밋을 가리키고 이동하지 않습니다. 주로 버전 릴리스나 중요한 이력 지점에 사용됩니다.
  1. HEAD:
  • HEAD는 현재 작업 디렉토리나 작업 트리의 상태를 나타내는 포인터입니다.
  • HEAD는 현재 체크아웃된 브랜치나 커밋을 가리키며, Git이 어떤 브랜치 또는 커밋을 작업 중인지 알려줍니다.
  1. 각 요소의 관계와 차이:
  • 커밋은 Git 저장소의 기본 데이터 단위로 스냅샷을 나타냅니다.
  • 브랜치는 커밋의 가리키는 참조로, 특정 시점의 작업을 추적하고 분리된 작업 흐름을 유지합니다.(새로운 커밋이 발생할 때 브랜치도 이동함)
  • 태그는 특정 커밋에 고정된 이름을 부여하여 중요한 이력 지점을 표시합니다.
  • HEAD는 현재 작업 중인 브랜치나 커밋을 가리키는 포인터로, 현재 상태를 나타냅니다.
  • 브랜치, 태그 및 HEAD 모두 커밋을 가리키지만 목적과 사용 방식에서 차이가 있습니다.

유용한 사이트

https://learngitbranching.js.org/?locale=ko

0개의 댓글