728x90

iOS 의 경우 Mac 과 함께 디버깅 하기 위한 궁합 및 도구가 편리하게 제공되고 있어서 어렵지 않게 Wireshark 로 기기의 패킷을 캡쳐할 수 있었습니다. 하지만 안드로이드 운영체제는 가상 인터페이스로 붙이는 방법이 없는 것처럼 보였고, 단말을 루팅하여 tcpdump 를 돌리는 것과 같은 방식들이 제안되고 있었습니다.

시험 기기로 확보한 기기가 삼성의 단말이고 제 소유가 아니다보니 루팅을 하는 것도 좀 꺼려지더군요. 그래서 찾아본 것이 바로 NOX Player 였습니다. 게임을 즐기는 사람들이면 안써본 사람이 없다는 NOX Player. 저는 게임을 하기 위해서도 아니고 안드로이드 기기의 패킷을 확인하기 위해서 NOX Player 를 처음 사용하게 되다니...


adb 를 통해 구동중인 NOX Player 의 안드로이드에 연결하기

우선 NOX Player 를 이용하여 적당한 안드로이드 이미지를 구동시킵니다. 기본적으로 Virtual Box 이지만 구동할 수 있는 이미지와 안드로이드 버전이 제한적인 것 같아 좀 아쉬웠습니다. API 버전이 안드로이드 운영체제 버전마다 차이가 있고, 이 차이가 실제 앱 구동에도 영향을 주는 것으로 알고 있습니다.

여튼, 안드로이드 운영체제가 잘 구동되면 NOX Player 로 62001 포트를 이용하여 연결이 가능해 집니다. 터미널에서 adb 를 이용하여 로컬호스트의 62001 포트로 연결을 맺어보겠습니다. 아래와 같은 명령을 사용하시면 되며, 정상적으로 연결된 경우 connected to 127.0.0.1:62001 이라는 메세지를 볼 수 있습니다. 

% adb connect 127.0.0.1:62001
adb server version (32) doesn't match this client (41); killing...
* daemon started successfully
connected to 127.0.0.1:62001

물론 iOS X Mac 과 달리 이렇게 연결했다 하여 바로 쉽게 Wireshark 로 직접 패킷을 볼 수 있는 것은 아닙니다. NOX Player 를 통해 TCP 덤프를 캡쳐해 줄 tcpdump 와 네트워크로 파일 내용을 전송해줄 netcat 을 복사하여 사용해야 합니다. 이 파일들을 이용하여 1) 파일로 떨군뒤 로컬 환경으로 복사하여 분석하거나 2) netcat 으로 전송 포트를 열어 adb 를 경유하여 wireshark 로 실시간으로 덤프를 보는 방법의 두가지 옵션을 쓸 수 있게 됩니다. 

 

안드로이드 기기로 tcpdump 와 netcat 파일 전송

우선 안드로이드 기기에서 구동되는 tcpdump 와 netcat 바이너리를 찾아야 합니다. 유통되는 왠만한 버전을 사용하는 것은 별 문제 없을거라 생각합니다. tcpdump 와 netcat 은 아래의 각 사이트에서 최근 버전을 다운로드 받으시기 바랍니다. (TCPDUMP : www.androidtcpdump.com/android-tcpdump/downloads, netcat : 실행파일만 받는게 좋은데... 경로를 잊어버렸습니다 ;; 찾는대로 다시 업데이트 해두겠습니다. )

안드로이드에서 사용할 유틸리티 2종이 준비되면 adb 의 push 명령을 이용하여 바이너리 파일을 NOX Player 의 안드로이드로 전송하도록 하겠습니다. 아래와 같이 가상 sdcard 의 경로 하위의 Download 폴더로 파일을 전송했습니다. 

% adb push netcat /sdcard/Download && adb push tcpdump /sdcard/Download
netcat: 1 file pushed. 27.1 MB/s (92156 bytes in 0.003s)
tcpdump: 1 file pushed. 48.3 MB/s (1889632 bytes in 0.037s)

/sdcard/Download 폴더로 전송한 파일을 다시 /system/xbin 경로로 이동시키도록 하겠습니다. 이 작업을 위해서는 adb 를 이용해 안드로이드 쉘에 접근해야 합니다. 아래와 같이 adb shell 명령을 입력하면 62001 포트를 통해 안드로이드 쉘에 접근할 수 있습니다. 일반적인 터미널에서처럼 cp 명령으로 파일을 옮기고, chmod 를 통해 실행 권한을 부여하도록 하겠습니다. chmod u+x 해도 무방합니다.

% adb shell
dream2lte:/ # cp /sdcard/Download/netcat /system/xbin/
dream2lte:/ # cp /sdcard/Download/tcpdump /system/xbin/
dream2lte:/ #
dream2lte:/ # chmod 755 /system/xbin/netcat
dream2lte:/ # chmod 755 /system/xbin/tcpdump

 

tcpdump 를 실행하여 pcap 파일로 패킷을 캡쳐하자

이제 패킷 덤프를 뜰 준비가 되었습니다. 일반적으로 사용하는 tcpdump 명령들을 대부분 사용할 수 있기 때문에 필요에 따라 옵션을 조합하시면 되겠습니다. 안드로이드의 모든 인터페이스로 들어오는 패킷을 캡쳐하여 /sdcard/Download 경로에 pcap 파일로 떨구는 명령의 예제는 아래와 같습니다. 캡쳐를 중지하려면 ctrl-c 등으로 중지 시그널을 보내시면 됩니다. 참 쉽죠?

dream2lte:/ # tcpdump -i any -n -s 0 -w /sdcard/Download/1557.pcap
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
^C73886 packets captured
88490 packets received by filter
1864 packets dropped by kernel

 

캡쳐한 pcap 파일을 로컬로 전송하여 분석해보자

이제 adb 의 옵션중 pull 을 이용하여 파일을 안드로이드 환경에서 로컬 환경으로 복사해 오도록 하겠습니다. . 소스, 목적지의 순서로 파라메터를 넣으면 되겠죠? 아래는 그 예제입니다. 캡쳐를 오랫동안 하지 않았지만 포트에 상관없이 모든 패킷을 캡쳐하다보니 양이 많습니다.

안드로이드 시뮬레이터의 성능에 영향을 줄 수 있으니 로컬 환경에서와 달리 tcpdump 를 사용할 때는 포트와 같은 조건을 꼼꼼히 넣어주시는 것이 좋습니다. 캡쳐된 pcap 파일이 로컬 환경으로 복사가 완료되면 wireshark 를 이용하여 파일을 열고 패킷을 분석하시면 됩니다. 

% adb pull /sdcard/Download/1557.pcap ./
/sdcard/Download/1557.pcap: 1 file pulled. 22.1 MB/s (96239260 bytes in 4.150s)

 

netcat 을 이용하여 실시간으로 패킷 분석하기

파일로 이용하여 패킷을 분석하는 것은 왠지 절차가 좀 복잡해 보입니다. 그리고 실시간으로 변화를 관찰할 수 없어 캡쳐가 잘못된 경우 다시 동일한 과정을 반복해야 합니다. 정상적인 사람인 우리들은 이런 불편함을 참을수가 없습니다 ㅎㅎ 이때는 netcat 을 이용해서 캡쳐되는 파일들을 특정 포트로 노출시켜 wireshark 가 받도록 하는 방법을 사용할 수 있습니다. 

1) 우선 터미널을 두개 띄웁니다. 하나는 adb shell 로 안드로이드에서 tcpdump 를 실행하는 목적이고, 다른 하나는 adb forward 로 로컬 환경의 wireshark 로 데이터를 보내는 목적입니다.

2) 1번 터미널 - 조금전과 마찬가지로 안드로이드 쉘에서 tcpdump 를 실행해야 합니다. 이때, 캡쳐된 내용을 파일로 떨구지 말고 파이프(|)를 사용하여 netcat 이 내용을 전달 받도록 하겠습니다. netcat 는 특정 포트 (아래에서는 12345) 로 전달 받은 내용을 전송하게 됩니다. tcpdump 에서 이 포트의 트래픽은 캡쳐하지 않도록 not port 12345 를 파라메터에 넣었다는 점도 참고해 주세요!

2) 2번 터미널 - 이제 로컬 쉘에서 adb forward 명령을 이용해 시뮬레이터의 프로토콜:포트를 로컬의 프로토콜:포트로 전달하겠습니다. 맥 환경에서의 netcat 인 nc 명령으로 해당 포트를 수신하고, 파이프를 통해 wireshark 로 수신된 내용을 전달하는 명령입니다. 

// 터미널 #1 (안드로이드 쉘에 접근) - tcpdump 로 패킷 떠서 netcat 으로 내보내기
% adb shell
% # tcpdump -i any -n -s 0 -w - not port 12345 | netcat -l -p 12345
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
^C2606396 packets captured
2779150 packets received by filter
164234 packets dropped by kernel

// 터미널 #2 (로컬 쉘) - netcat 이 내보내는 것 받아서 wireshark 로 넘기기
% adb forward tcp:12345 tcp:12345 && nc 127.0.0.1 12345 | wireshark -k -S -i -

다소 번거롭지만 NOX Player 를 이용하여 안드로이드 기기의 패킷을 캡쳐하고 로컬의 wireshark 로 전달하여 분석하는 두가지 방법을 살펴보았습니다. 기기를 루팅하지 않고 패킷을 캡쳐할 방법이 없기 때문에 시뮬레이터로 부담 없이 패킷을 분석해 보시기 바랍니다. 

 

728x90
728x90

개발을 하던 다른 트러블 슈팅을 하던 기기의 패킷을 추출해야 하는 경우들이 많습니다. Mac 을 사용하는 경우 rvi (Remote Virtual Interface) 를 이용해서 기기를 연결해서 쉽게 와이어샤크 Wireshark 같은 물건으로 패킷을 캡쳐할 수 있습니다. 말 그대로 가상 네트워크 인터페이스로 iOS 기기를 설정하기 때문이죠.

개인 기기로 아이폰을 쓰다보니 안드로이드는 샤오미 홍미4 이후 오랫동안 쓴적이 없었습니다. 그나마도 딸래미 학교 들어가면서 비상연락용 겸 슬랙 서적 집필할 때 화면 캡쳐용으로 산거라 진심을 다해서 써보지도 않았습니다. 허나, 현실에서는 안드로이드 환경의 패킷을 확인해야 하는 일이 종종 생기더군요.


ADB, 안드로이드 디버그 브릿지

이유는 잘 기억나지 않지만 제 Mac 에도 안드로이드 스튜디오 Android Studio 가 이미 설치되어 있었습니다 -_-;; ADB 는 Android SDK 개별 설치 혹은 Android Studio 설치시 SDK 에 딸려서 설치되는 디버그 툴인 것 같습니다. 패킷을 뜨기 위해 기기를 연결할 필요가 있었는데요 (사실은 NOX 로 기기 에뮬레이션해서...) ADB 가 그냥 실행이 되지는 않더군요.

Android Studio 가 정상적으로 동작하고 있다면 ADB 는 어딘가에 잘 설치가 되어 있는 상태입니다. 제 경우에는 아래의 Path 에서 해당 내용을 확인할 수 있었습니다. 아마 대부분 비슷한 경로에 설치가 되어 있을거라 생각합니다. 

% pwd
/Users/nopd/Library/Android/sdk/platform-tools

 

Path 로 경로 잡아주기

보통 SDK 가 설치되면 자동으로 Path 를 설정해 주는 경우가 많은데 Android SDK 는 그러지 않나 봅니다. (혹은 제가 영어로 나온 메세지를 놓친 것일지도... 속닥속닥...) 제 경우 필요한 터미널 환경 설정을 .bash_profile 에 하고 있어서 아래와 같이 Android SDK 의 Platform tools 경로를 추가해 주었습니다. 이렇게 해주고나니 어디서든 adb 를 실행할 수 있게 되었습니다 ㅎㅎ 

# Setting PATH for Android Platform Tools (esp for ADB)
export PATH="${PATH}:/Users/nopd/Library/Android/sdk/platform-tools"

그럼! 즐거운 디버깅 되시길 기원합니다. 이제 저는 NOX 와 씨름하러...

728x90
728x90

이제 본격적으로 프로젝트의 내용물을 채워보도록 하겠습니다. 별도의 외부 데이터베이스를 사용하지 않고 기본적으로 제공되는 파일 기반의 데이터베이스인 Sqlite 를 그대로 사용하도록 하겠습니다. 데이터베이스를 쓰기 위해서 먼저 기본 테이블을 생성해야 하는데요, Django 는 데이터베이스를 이용하는 것을 전제로 사용자와 사용자 권한 그룹 테이블을 알아서 만들어 주도록 되어있습니다. 

 

기본 테이블의 생성

기본 테이블을 생성하거나 프로젝트에 필요한 테이블을 생성하는 것 모두 manage.py 가 제공하는 명령어를 이용할 수 있습니다. 기본 테이블의 구조는 미리 정의가 되어 있기 때문에 모델을 만드는 작업을 하지 않고 사용이 가능합니다. 프로젝트의 루트 경로에서 manage.py migrate 명령을 사용하여 기본 테이블인 admin, auth, contenttypes, sessions 의 4개 테이블을 생성할 수 있습니다. 

% python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

migrate 명령이 수행되고 나면 settings.py 에 지정된 기본 데이터베이스 정보에 따라 Sqlite 용 파일이 프로젝트 루트 경로에 생성된 것을 보실 수 있습니다. 추후 Django 에 익숙해져 외부 데이터베이스를 사용하는 경우에는, 해당 데이터베이스 인스턴스에 4가지 테이블이 생성된다고 보시면 되겠습니다. 

 

프로젝트용 테이블의 생성 

기본 테이블은 Django 를 이용한 과제의 공통 테이블의 성격입니다. 수퍼 유저의 정보와 같은 것들이 이곳에 저장되는 것이지요. 실제 프로젝트에서 사용할 테이블을 정의하고 생성해야 하겠죠? 지난 포스팅 이후 뭘 만들어 볼까 고민하다가... 인터넷 서핑을 하면서 마음에 드는 이미지를 모아두는 서비스를 만들어 보면 어떨까 생각을 해보았습니다. (그닥 재미있어 보이진 않는군요...)

이미지의 이름 (Title) 과 이미지의 경로 (URL) 이고, 추후 검색 기능등을 넣기 위해 태그 (Tags) 정보를 입력받아 저장해보겠습니다. 지난 시간에 추가한 어플리케이션인 myfirstapp 폴더에 생성된 여러 파일들 중 models.py 를 열겠습니다. 이 파일에는 어플리케이션이 사용할 데이터, 테이블의 구조가 기술되며 이를 기반으로 manage.py 가 데이터베이스에 테이블 생성 작업을 대행해주기도 합니다. 

물론 별도로 데이터베이스를 수정하고 내용을 models.py 에 반영하는 것도 가능하지만 models.py 를 먼저 수정하고 manage.py 를 이용해서 데이터베이스 작업을 하는 것이 초보자에게는 좋다고 생각합니다. 사실 회사에서 과제를 진행하면서 migrate 과정에 대한 의문이 좀 많았는데 원격지의 리얼 데이터베이스를 쓰는 경우에는 migrate 을 잘 활용하는 것이 DBA 의 눈도 피할 수 있어서 좋을 것 같군? 하는 생각도 좀 들긴 합니다. 

 

이번 포스팅에서는 테이블 구조를 기술할 때 사용하는 django.db.models.Model 클래스를 자세히 살펴보지는 않겠습니다. 아직 공부를 못한 것도 있고 (퍽퍽...) 일단은 과제 하나를 잘 수행해 보는 것이 좋다고 생각하기 때문입니다 (후훗). 눈으로 보더라도 최대 길이라던가 빈 값의 허용, null 도 허용할 것인가와 같은 우리가 데이터베이스에서 테이블을 만들때 입력하는 정보들이 대부분 기술된다고 보시면 되겠습니다. 

Admin 사이트에 생성한 테이블 반영

admin.py 를 수정하면 생성한 테이블 정보를 django 가 제공하는 기본 어드민 페이지 (0.0.0.0:8000/admin) 에서 관리하거나 간단한 데이터 입출력 작업을 할 수 있게 됩니다. 지난 포스팅에서 이야기 했는지 기억이 잘 안납니다만 php 에서 쓰는 phpmyadmin 과 같은 역할이라고 생각하시면 편합니다. 우리가 생성한 어플리케이션인 myfirstapp 폴더 하위의 admin.py 를 열어서 아래와 같이 수정해 보겠습니다. 

 

테이블을 Sqlite 데이터베이스에 반영하려면 manage.py 가 제공하는 makemigrations 와 migrate 명령을 사용하게 됩니다. makemigrations 는 migrate 명령이 이해할 수 있도록 models.py 에 기술된 내용을 확인하고 현재의 데이터베이스와 비교하여 변경이 필요한 부분을 추출, python 코드로 만드는 역할을 수행합니다. migrate 은 이렇게 정리된 내용을 실제로 데이터베이스에 반영하는 역할을 하는 것이겠죠?

명령을 수행하기전에 어플리케이션 폴더인 myfirstapp 하위의 migrations 폴더를 살펴보면 __init__.py 파일만 존재하고 아무런 내용이 없는 것을 확인할 수 있습니다. makemigrations 명령을 수행한 후에 해당 폴더의 내용들이 어떻게 바뀌는지 살펴보도록 하겠습니다. 

 

명령을 수행하고 나면 myfirstapp/migrations 폴더에 0001_initial.py 라는 파일이 생성된 것을 볼 수 있습니다. 느낌은 첫번째 마이그레이션 작업이라는 느낌이죠? 이 파일을 열고 내용을 살펴보면 데이터베이스 작업에 필요한 파일로 조금전에 models.py 에 업데이트 했던 내용들이 들어가 있는 것을 확인할 수 있습니다. 

% python3 manage.py makemigrations
Migrations for 'myfirstapp':
  myfirstapp/migrations/0001_initial.py
    - Create model ImageCollector

 

이제 manage.py 의 migrate 명령으로 생성된 마이그레이션 작업 파일을 수행하여 데이터베이스에 반영되도록 하겠습니다. 기본 테이블로 생성한 admin, auth, contenttypes, sessions 에 대해서도 변경 사항이 있는지 점검하는 것을 볼 수 있습니다. ImageCollector 모델을 만들면서 지정한 max_length 지정 값은 auth 테이블에도 업데이트가 필요한 모양입니다. 알아서 잘 챙겨주니 참 고맙습니다. :-)

% python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, myfirstapp, sessions
Running migrations:
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying myfirstapp.0001_initial... OK

 

이렇게 이번 포스팅에서는 기본 테이블을 생성하고 프로젝트에서 사용할 테이블을 생성해 보았습니다. 이렇게 만든 테이블을 확인하는 쉬운 방법은 장고가 제공하는 Admin 사이트를 이용하는 것입니다. 다음 포스팅에서는 Admin 사이트 접근을 위한 수퍼유저 계정의 생성을 해보고 생성된 ImageCollector 테이블에 간단한 샘플 데이터를 넣어보도록 하겠습니다. 

728x90
728x90

개발을 전문으로 하고 있는 Role 이 아니다 보니 할 때마다 헷갈리는 깃. 그래서 이슈를 하나씩 해결 할 때마다 블로그 포스트로 정리를 하고 있습니다. 오늘은 같은 코드가 여러 원격 저장소에 있을때 각 브랜치를 로컬로 체크아웃하여 사용하는 방법에 대하여 정리를 해봤습니다. 


추가 원격 저장소 등록하기

우선 여러 원격 저장소가 있는 경우에는 각 원격 저장소를 로컬 저장소에 원격 저장소(Remote Repository) 로 등록을 해야 합니다. 원격 저장소를 등록하는 것은 git remote add 명령을 이용해서 추가해줄 수 있습니다. 이전 포스팅에 정리된 내용이 있으니 아래 글을 참고하시기 바랍니다

 

git & github / 포크한 저장소와 원본 저장소를 다시 동기화 하려면?

깃허브 Github 에 공개되어 있는 코드를 개량할 때, 회사의 Git 에 등록된 과제의 기능을 개발할 때 우리는 포크 Fork 를 통해 원격 저장소의 코드를 내 저장소로 옮긴후 작업을 하게 됩니다. 내 저장

ondemand.tistory.com

 

원격 저장소의 브랜치 정보 업데이트 

원격 저장소가 등록되었으면 이제 각 원격저장소의 브랜치 정보를 업데이트 해야합니다. git remote update 명령을 이용하면 현재 로컬 저장소에 지정되어 있는 모든 원격 저장소의 브랜치 정보를 업데이트 하게 됩니다. 아래와 같이 origin, CDN 이라는 두개의 원격 저장소가 지정되어 있다면 두 곳의 브랜치 정보를 가져오게 되는 거지요.

% git remote update
Fetching origin
Enter passphrase for key '/Users/nopd/.ssh/id_rsa': 
Fetching CDN
Enter passphrase for key '/Users/nopd/.ssh/id_rsa':

 

업데이트된 브랜치 정보의 확인

브랜치 목록이 잘 전달 되었는지를 확인하기 위해서는 git branch -a 명령을 사용하면 됩니다. 원격 저장소와 브랜치는 remotes/ 로 시작하는 브랜치들입니다. 실수 origin 브랜치에 만든 CDN/master 브랜치도 보이는군요. 

% git branch -a
* master
  remotes/CDN/master
  remotes/origin/HEAD -> origin/master
  remotes/origin/CDN/master
  remotes/origin/master

 

다른 원격 저장소의 브랜치 체크아웃하기

여러 원격 저장소를 사용할 때의 주의점은 이름의 충돌입니다. 요즘 논란이 되고 있는 이름이긴 합니다만 여전히 저의 많은 저장소들은 master 를 기본 브랜치로 사용하고 있습니다. 때문에 서로 다른 원격 저장소의 master 브랜치를 그대로 체크아웃 하는 경우에는 로컬 브랜치에서 충돌이 일어나게 됩니다. 

이를 막기 위해서는 체크아웃할 때 로컬 저장소의 이름을 [원격저장소이름/브랜치명] 의 네이밍 컨벤션을 따라가면 편리합니다. 다른 방법으로 해도 문제는 없지만 여러가지 방법중 원격 저장소의 이름을 앞에 넣어주는 것이 개인적으로는 가장 편리하고 헷갈리지 않았습니다. git checkout 명령에 -b 옵션을 주어 체크아웃 해보도록 하겠습니다. 

% git checkout -b CDN/master CDN/master
Branch CDN/master set up to track remote branch master from CDN.
Switched to a new branch 'CDN/master'

체크아웃 후 나온 메세지를 읽어보면 "CDN (저장소) 로부터 master 브랜치를 이용하여 (로컬 저장소에) CDN/master 라는 브랜치를 셋업 했습니다" 라는 내용입니다. 정확한 저장소로부터 브랜치를 가져온 것을 확인하실 수 있죠? 나오는 메세지가 영어라고 당황하지 마시고 항상 읽는 습관을 들이는 것이 좋습니다!

 

다른 원격 저장소의 브랜치 푸시하기

이렇게 다른 원격 저장소의 브랜치를 체크아웃 한 뒤에는 평소처럼 수정, 로컬 커밋을 하시면 됩니다. 그런데, 로컬 커밋을 완료한 후 원격 저장소에 다시 푸시하려면 어떻게 해야할까요? 뭔가 헷갈릴 때는 git push 명령만 입력하여 자세한 안내를 받는 것을 추천드립니다. 아래의 명령은 현재 브랜치를 확인한 후 원격 저장소에 푸시하기 위해 git push 명령을 입력하여 안내를 확인해 본 내용입니다. 

% git branch
* CDN/master
  master
  
% git push
fatal: The upstream branch of your current branch does not match
the name of your current branch.  To push to the upstream branch
on the remote, use

    git push CDN HEAD:master

To push to the branch of the same name on the remote, use

    git push CDN CDN/master

git push 명령을 인자 없이 입력했을 때 나온 안내 메세지도 읽어봅시다. fatal 이 떠서 왠지 무섭지만 "아주 주의해야 해!" 라는 의미로 받아들이시면 됩니다. 현재 로컬 저장소에서 작업중인 브랜치가 원격 저장소의 이름과 일치하지 않아 나온 경고입니다. 제 경우를 보면 원격 저장소 (CDN) 의 master 브랜치를 로컬 저장소에 CDN/master 로 체크아웃했으니 master <-> CDN/master 라고 보시면 됩니다. 

이를 푸시하는 방법을 두가지일텐데요, 원격 저장소의 master 브랜치에 바로 푸시를 하려면 첫번째 안내처럼 git push [#원격저장소명#] HEAD:[#브랜치명#] 을 쓰면 됩니다. 만약 로컬 저장소에서 지정한 이름인 CDN/master 를 새로운 브랜치로 만들면서 푸시하려면 두번째 명령의 가이드를 따르면 됩니다. 참 쉽죠!?

 

원격 저장소의 브랜치 엿보기만 하려면?

마지막으로 원격 저장소의 브랜치를 수정할 생각은 없지만 로컬에서 살펴보고 싶을때 쓰는 방법입니다. 이때는 git checkout 에 넣었던 -b 옵션을 빼주기만 하면 됩니다. 로컬에서 마음껏 수정해보고 커밋도 하다가 다시 동일한 브랜치를 체크아웃하면 변경 사항은 그대로 제거됩니다. 만약 수정한 내용을 보존하고 싶다면 새로운 브랜치로 만들면 되겠죠? git checkout 명령에 -b 옵션을 다시 넣고 새로운 브랜치명을 넣어주면 끝!

% git checkout CDN/master
Note: checking out 'CDN/master'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

 

728x90

+ Recent posts