반드시 알아야하는 git 기본 사용 가이드

1. 절대경로와 상대경로

 

1-1) 절대경로: 루트부터 목적지점까지 거치는 모든 경로 전부 작성하는 것

 

예시) 바탕화면까지 절대경로

 

C:/Users/ssafy/Desktop

 

 

1-2) 상대경로: 현재 작업하고 있는 디렉토리 기준으로 계산된 상대적 경로

 

예시) 바탕화면의 상대경로

 

현재 작업 디렉토리 > C:/Users

 

여길 기준으로 바탕화면의 상대경로? ssafy/Desktop

 

 

2. git 사용 가이드

 

2-1) 작업환경 세팅

 

그냥 윈도우 검색해서 git bash을 시작하면 작업환경이 없는데

 

 

내가 원하는 작업환경을 기본환경으로 가지고 가고 싶다면

 

code 폴더(원하는 폴더)에서 마우스 오른쪽 클릭하고 'git bash here' 클릭

 

 

이러면 기본 작업환경을 별다른 명령어 없이 ~/Desktop/code로 시작할 수 있다

 

 

2-2) 반드시 익혀야하는 기본 명령어

 

1. touch (파일이름).(확장자) : 파일을 생성

 

 

폴더는 생성하지 못한다

 

 

 

2. mkdir (폴더이름) : 폴더를 생성

 

' ', " " 로 둘러싸지 않아도 인식해준다

 

 

3. ls : 현재 작업중인 디렉토리의 폴더, 파일 목록을 보여준다

 

 

4. rm (파일이름) : 해당 파일을 삭제함

 

vs. rm -r (폴더이름): 해당 폴더를 삭제함

 

반드시 -r 옵션을 줘야 폴더를 삭제하고 그렇지 않으면 에러남

 

 

5. start (폴더/파일이름): 해당 폴더/파일을 여는 명령어

 

맥은 open을 사용한다고함

 

 

윈도우에서는 open을 찾지 못함

 

 

 

start C++을 사용하면..?

 

 

이렇게 C++ 폴더가 열린다

 

python 폴더도 똑같이 열어보면?

 

 

python 프로그램이 열리네?? 폴더를 열고싶다면..? 절대경로를 사용하자

 

 

 

6. cd (경로): 현재 작업중인 디렉토리를 해당 경로로 변경시킨다

 

절대경로, 상대경로 모두 활용가능하다

 

 

 

현재 바탕화면에서 시작한다고 할 때 바탕화면에 있는 code 폴더로 이동하고 싶다면?

 

상대경로로 이동: cd code

 

절대경로로 이동: cd C:/Users/OHYUBEEN/Desktop/code

 

 

cd .. : 현재 경로에서 한 부모 폴더 뒤로 이동함

 

cd . : 현재 경로를 지정함(이동하지 않음)

 

 

뒤로는 cd ..으로 가는데 앞으로는 어떻게 감??

 

당연히 앞으로 갈 폴더를 지정해야 앞으로 가지

 

Desktop 앞에 있는 code폴더로 가고 싶으면 cd code

 

code 폴더 내에 PYTHON으로 이동하고 싶으면 cd PYTHON

 

 

조금 더 응용해본다면.. 만약 두 부모 뒤로 이동하고 싶으면??

 

cd ../..을 하면 Desktop으로 이동할거임

 

거기서 code 내의 java 폴더로 가고 싶다면?? cd code/java 하면 되겠지

 

 

 

그렇다면 . 과 ..을 모두 활용해서 code 폴더로 가고 싶다면??

 

cd ../. 을 하면 되겠지?

 

 

3. git의 기본 용어

 

 

3-1) README.md

 

프로젝트에 대한 설명 문서

 

깃허브 프로젝트에서 가장 먼저 보게된다

 

SW와 함께 배포하고 작성 형식은 따로 없지만 보통 마크다운을 이용해서 작성함

 

 

3-2) Repository?

 

특정 디렉토리의 버전 관리를 위한 저장소

 

저장소를 만들고 싶은 폴더에서 - git bash here을 누르고 - $ git init으로 local repository를 구축

 

 

3-3) commit?

 

저장소 내용을 특정 버전으로 남기는 것

 

commit은 working directory, staging area, repository 3가지를 바탕으로 동작함

 

working directory는 작업하고 있는 현재 디렉토리

 

staging area는 commit으로 남기고 싶은, 특정 버전으로 관리하고 싶은 파일들의 모음

 

repository는 commit한 내용들이 저장되어 있다

 

 

working directory의 파일을 git add를 통해 staging area에 올리고

 

staging area에 올라온 파일을 git commit하면 영화의 장면, snapshot처럼, 버전형태로 commit들이 repository에 저장된다

 

commit을 하면 git이 변경이유, 변경사항 시간 등을 모두 알아서 추적하게 된다

 

---------------------------------------------------------------------------------------------------

 

snapshot이 무슨말이냐?

 

 

위와 같이 작업을 하다가.. A.txt와 B.txt에 각각 python!, morning!이라는 단어를 추가로 넣었다

 

git add B.txt만 수행하여 staging area에 올리고 commit을 수행함

 

 

그러면 working dir에서 A.txt를 수정했음에도 불구하고 git add를 하지 않아서 ver_2에 hello 상태로만 있고

 

B.txt는 수정하고 staging area에 올려서 repo의 ver_2에 morning!이 반영되어 있다

 

수정 작업을 했더라도 staging area에 올리지 않으면 commit에 반영되지 않는다

 

--------------------------------------------------------------------------------------------------------------------------------------------------

 

중간에 staging area를 왜 거치나??

 

1) 조금 더 세밀한 버전 관리가 가능하다

 

working directory의 모든 파일들을 수정했다고 하더라도 일부는 완료되지 않을 수가 있어서 그 최신 모습을 commit에 반영하고 싶지 않을 수 있다

 

그래서 최신 모습을 반영하고 싶은 파일들만 staging area에 올려두고 그것들만 commit할 수 있게 된다

 

 

하지만 working directory가 없다면? 원하는 것들만 선별적으로 commit 할수가 없고, 불완전한 파일을 사용자들에게 보여주게 되어 세밀한 버전관리가 쉽지 않다

 

 

2) 똑같은 파일들을 가지고 여러명이 서로 다르게 수정해서 commit으로 올리다가 충돌이 일어나는 경우를 검사하여 방지함

 

서로 덮어쓰다가 꼬일 수 있거든

 

--------------------------------------------------------------------------------------------------------------------------------------------------

 

 

4. git의 local repository 구축하기

 

4-1) git init

 

현재 작업 디렉토리를 저장소로 버전관리하기 위해 local repository로 초기화를 수행

 

이때 작업 디렉토리 옆에 (branch 이름)이 표시되고 작업 폴더 내부에 .git이 생성됨

 

 

git에서 기본으로 설정되어 있는 branch 이름은 master

 

근데 .git이 안보이는데 폴더 상단 메뉴 '보기' - 숨은 항목 보기 누르면 보인

 

 

4-2) git status

 

git이 관리하고 있는 local repository의 상태를 보여준다

 

git add, git commit 등을 수행하면 아무 말도 없는데 git status를 통해 적극적으로 상태를 확인해야한다

 

 

on branch master로 branch이름 master 보이고 no commits yet으로 git이 관리하고 있는 파일이 없다는 것. commit이 한번도 없다는 것

 

파일 만들고 git add로 track하라고도 조언해줌

 

 

4-3) git add

 

현재 local repository내에서 '추적되지 않은 작업하고 있는 파일'(untracked)이나 추적파일(tracked) 중에서 수정된 파일(modified) 모두 staging area로 옮긴다

 

git add . 하면 현재 작업 디렉토리 내의 모든 파일들을 staging area로 옮긴다

 

git add (파일이름) 하면 특정 파일만 staging area로 옮긴다

 

 

git add a.txt를 하면 'changes to be committed'로 staging 단계에 a.txt 파일이 있고

 

git add하지 않은 파일은 untracked라고 되어 있다

 

여러개의 파일을 하고 싶다면?? 공백으로 구분해서 여러개의 파일을 쓰면 된다

 

git add a.txt b.txt 하면 a.txt와 b.txt를 staged 단계에 올린다

 

 

git add . 하면 모든 파일이 한번에 staged로 올라간다

 

 

 

4-4) git config --global user.email, git config --global user.name

 

git add를 하고 git commit을 해볼려고 하면

 

위와 같이 git config --global user.email과 git config --global user.name을 통해 자기가 누구인지를 밝히라고 함

 

github 메일이랑 github 닉네임 정하면 된다(다른것도 될것 같긴함)

 

 

한번 설정해두면 컴퓨터 껐다 켜도 계속 유지되어 있다

 

이러한 설정을 삭제하고 싶으면

 

git config --unset --global user.email

git config --unset --global user.name

 

 

 

4-5) git commit -m "(message)"

 

staging area에 올라온 파일을 commit시킨다

 

commit message는 최대한 자세하면서도 간단하게 그리고 반드시 쓰는게 좋다

 

 

a,b,c,d.txt 파일 모두 삭제하고 새롭게 e,f,g,h.txt 파일 만든다

 

앞에서 a,b,c,d가 이미 commit 되어서 git이 계속 추적하고 있음을 확인하자.

 

그래서 삭제했다는 것도 추적하고 있음을 볼 수 있다. 다시 git add . 하고 git commit을 해보면

 

 

commit을 수행하면 그 순간의 버전이 스냅샷처럼 .git 폴더에 저장된다고함

 

근데 어디있는지는 모르겠다.. 이진파일로 인코딩되어서

 

object 폴더에 있다고 하고

 

index 파일은 staging area에 있는 파일이라고 하는데

 

commit message가 .git에 있는거 보면 .git 어딘가에 저장되긴 하나보다

 

 

5. github repository로 구축하기

 

이제 commit을 수행하여 local repository에 저장했지만 실제로 볼려면 github repository와 연동하여 저장시켜야한다

 

5-1) github repository 만들기

 

자기 github 아이디로 들어가서 새로운 repository를 만든다

 

 

자기 아이디 로그인하고 우측 상단 프로필 옆에 +버튼 누르면 New repository 보인다

 

 

owner, name, description, public/private, add a readme file 등을 선택하고 생성

 

 

그러면 위와 같이 어떻게 연동하는지 친절하게 알려줌

 

 

5-1) git remote add origin (github repository 주소)

 

위에서 github repository 고유 주소를 복사하고 git remote add origin (주소) 입력

 

local repository와 github repository를 원격으로 연결시킨다

 

 

아무 말 없으면 remote 연동이 된 것

 

5-2) git push -u origin (branch이름)

 

이제 commit된 상태를 remote repository에 저장시킬려면..

 

git push -u origin (branch이름)을 입력

 

local repository의 최신 내용을 (branch이름)의 branch로 github repository에 저장함

 

branch 이름은 git bash의 디렉토리 옆에 ( ) 안에 쓰여있는거로 기본은 master임

 

참고로 -u는 생략해도 된다

 

 

처음 push하면 위와 같이 인증하라고함

 

아무나 push하는걸 막을려고 그러겠지

 

보면 browser/device랑 token 인증 둘다 있음

 

 

browser 인증은 로그인하면 되고

 

 

sign in with a code하면 위와 같이 code 입력하라고 나오고 로그인해서 코드 입력하면 끝

 

 

token의 경우 우측 상단 자기 프로필 동그라미 누르고 settings로 들어가서

 

 

왼쪽 메뉴 맨 아래에서 developer settings를 누르고

 

 

personal access tokens를 누르고 generate new token을 누르면 

 

토큰 설명(note), 토큰 기한, 토큰에 대한 사용 범위까지 지정할 수 있고 생성하면

 

 

다음과 같이 빨간색 줄 부분에 token이 나온다.

 

페이지를 한번 벗어나면 다시는 볼수없으므로 어딘가에 저장해놓고 쓰든지 해야함

 

 

 

어떻게든 인증하고 나면 push가 수행된다

 

 

push하고 나서 만든 github repository를 보면 다음과 같이 저장되어 있다는 것을 확인할 수 있다

 

 

5-3) git clone (github repository url)

 

github repository의 내용을 현재 작업하고 있는 local repository로 복사함

 

 

위와 같이 code 버튼에서 clone을 위한 고유 url을 복사함

 

이거는 git remote add origin에 사용한 url과 동일함

 

 

git init 하지 않고 해도 clone은 가능

 

 

 

5-4) git pull origin master

 

A의 내용을 repository에 push하고 나서 새로 만든 B의 내용을 repository에 push하려고 하면

 

 

git이 위와 같이 서로 다른 내용을 repository에 push하려고 한다면서 막는다

 

이런 경우를 위해 git pull origin (branch)를 통해 github repository의 내용을 local repository로 끌어와야한다.

 

그래야 git이 동일한 프로젝트라고 인식한다

 

습관처럼 B의 내용을 commit하기 전에 pull을 먼저 해야한다고 하신다..? commit하기 전에 말고 하고 나서 해도 되는것 같기는 한디

 

 

differ이라는 폴더를 새로 만들고 앞에서 만든 repo에 push하려고 하면 위와 같이 에러남

 

 

git pull origin master를 이용해 github repo의 내용을 differ에 끌어온다

 

 

근데 바로 되는 경우도 있는데

 

간혹 위와 같이 fatal: refusing to merge unrelated histories라고 뜬다면

 

git pull origin master --allow-unrelated-histories라고 수행해야한다고 한다.

 

이 명령 옵션은 이미 존재하는 두 프로젝트의 기록(history)을 저장하는 드문 상황에 사용된다고 한다.

 

즉, git에서는 서로 관련 기록이 없는 이질적인 두 프로젝트를 병합할 때 기본적으로 거부하는데, 이것을 허용해 주는 것이다.

 

 

위와 같이 성공하고 differ 파일을 보면

 

 

repo의 내용도 복사해왔고 만약 a.txt와 b.txt만 repo에 올리고 싶다면 e,f,g,h를 삭제하고 올리면 된다

 

pull로 끌어왔으니까 어쨌든 관련있는 프로젝트라고 인식함

 

 

그래서 github를 확인해보면

 

 

아니 e,f,g,h가 왜 살아있지???

 

그거는 rm으로 삭제하고 나서 commit을 하지 않았기 때문임..

 

 

delete 시킨 commit이 보인다는 것을 확인할 수 있고 이번에 확인해보면..?

 

 

5-4) git push origin +(branch)

 

혹은 위 과정이 귀찮다면 강제로 병합시킬 수 있다

 

당연하지만 새로 만든 B가 github repository와 관련있는 프로젝트라고 확신할때만 사용하는 걸 추천

 

 

이러면 강제로 병합시켜서 바로 바뀐걸 확인할 수 있다

 

 

 

6. 기타 명령어

 

6-1) git branch (생성하고자 하는 branch 명)

branch를 새로 생성한다

 

단, 현재 local repository가 1번이라도 commit되어야 한다. 그렇지 않으면 에러남

 

 

branch는 동일 프로젝트에 대해 각각 서로 다른 작업을 수행하는 가지같은 개념이라고 생각하면 될 것같다

 

branch끼리의 작업은 서로 영향을 주지 않는다

 

 

6-2) git branch

 

현재 존재하는 모든 branch 목록을 보여줌. 위에서 초록색 부분은 현재 작업하고 있는 branch

 

 

6-3) git checkout (branch명)

 

해당 branch로 작업 branch를 이동함

 

 

6-4) git branch -M (변경하고자 하는 branch명)

 

현재 작업하고 있는 branch 이름을 변경

 

 

6-5) git branch -d (branch 명)

 

해당 branch를 삭제

 

현재 작업하고 있는 branch는 삭제 못하는듯

 

 

6-6) git log

 

commit한 내용을 확인

 

 

6-7) git diff 

 

unstaged 영역에서 파일의 변경 사항을 보여준다

 

당연하지만 tracked 상태여야 파일의 변경사항을 추적할 수 있다

 

 

위와 같이 a.txt에 'hello'를 추가하고 git diff를 수행하면 'hello'가 추가되었다고 변경내용을 보여줌

 

여기서 git add .로 staging으로 옮기고 git diff를 수행하면? 아무것도 출력하지 않는다.

 

git diff는 unstaged 영역의 변경내용만 보여주기 때문이다

 

 

그러면 여기서 a.txt에 python을 넣고 git diff를 해보면?

 

local repository가 unstaged 영역이고 여기 있는 파일이 수정되었으니까

 

python이 추가되었다고 출력해줌

 

 

6-8) git diff --cached

 

staging 영역 파일의 변경사항을 보여준다

 

그러면 여기서 git diff --cached를 수행하면 staging 영역에 있는 파일들의 변경사항을 알려준다

 

무엇이 나올까? 'hello' 상태의 a.txt와 아무것도 없는 b.txt를 staging으로 올렸었기 때문에 'hello'가 들어갔다고만 출력될 것이다.

 

이것으로 staging과 working directory 개념을 더 잘 이해했으면 좋겠다

 

 

6-9) git rm --cached (파일 이름)

 

staging 영역의 파일들을 다시 unstaging시키는 명령어

 

 

a.txt를 staging에 올리고 git status를 보면 git rm --cached (파일이름)을 수행하면 unstage 시킬 수 있다고 나온다

 

실제로 해보면 unstaging 된다는 것을 확인할 수 있다

 

 

 

7. 몇가지 에러 해결 가이드 + 팁

 

 

1) 일반적으로 복사 붙여넣기는 ctrl + C, ctrl + V로 알고 있지만 git bash내에서는 먹히지 않는다

 

ctrl + insert가 git bash내에서 텍스트 복사이고 shift + insert가 복사된 것을 git bash내로 붙여넣기

 

 

 

2) 절대경로 단순히 복사 붙여넣기 하면 다음과 같이 나오는데

 

C:\Users\OHYUBEEN\Desktop\code\python

 

 

이 경우 에러남

 

역슬래시(\)를 슬래시(/)로 고치거나 역슬래시 2번(\\)사용해서 해결

 

 

 

3) 명령어는 대소문자를 기본적으로 구분하지 않는다

 

중간에 대문자를 섞어써도 인식함

 

 

파일, 폴더이름은 조금 특이한데 이미 소문자로 적혀있으면 대문자로 쓰는 경우 에러나는데

 

소문자로 된 것이 없으면 대문자로 생성할 수 있다

 

다른 컴퓨터에서는 상관 없었던것 같은데 컴퓨터마다 다른것 같다

 

아무튼 명령어는 대소문자 구분하지 않는다는게 중요

 

 

 

4) 파일의 상태

 

tracked/untracked/modified/unmodified

 

working directory에 존재하는 파일은 tracked/untracked로 나뉜다

 

git은 한번이라도 버전 관리를 수행한(commit을 수행한) 파일을 tracked로 분류하고

 

버전관리를 수행하지 않은 것은 untracked로 분류함

 

 

위와 같이 최초로 생성된 파일은 untracked로 구성될 것이다. 왜냐하면 버전 관리를 수행하지 않았으니까

 

a.txt를 열어서 hello를 넣어 수정한 다음에

 

 

다시 한번 git status로 확인해봐도 여전히 두 파일은 untracked

 

 

이제 a.txt를 git add, git commit을 수행하여 버전관리를 수행하면

 

보면 a.txt는 untracked file에 빠져있다

 

 

다시 a.txt를 열어서 python이라고 추가하여 수정하고 git status로 상태를 확인해보면

 

 

다시 modified에 a.txt가 추가되었음을 알 수 있다

 

git은 이처럼 한번이라도 commit한 파일은 그 상태를 계속해서 추적한다.

 

앞에서 commit하지 않은 파일은 hello라고 수정했음에도 untracked라고 떠있지만 commit하고 나서 python을 추가했더니 modified라고 표시되어 있다

 

이러한 파일을 tracked 파일이라 부르고 한번이라도 commit하지 않은 파일을 untracked라고 부른다

 

 

tracked 상태인 파일은 unmodified / modified / staged 상태로 나뉜다

 

이제 새롭게 a.txt, b.txt를 만들고 둘다 commit한 다음에 git status를 사용하면

 

 

위와 같이 nothing to commit, working tree clean이 뜨고 untracked는 뜨지 않는다

 

현재 tracked 상태인 파일들이 아무것도 수정되어 있지 않다는 뜻으로 unmodified 상태이다

 

 

b.txt를 열고 123을 넣어서 수정한다음에 git status로 확인해보면 b.txt만 modified 상태라고 표시된다

 

현재 changes not staged for commit이라고 표시되어 있는데 b.txt를 git add하면..

 

 

changes to be committed로 되어 있는데.. 이를 commit 직전에 staging area에 올라와있다고 staged라고 부른다

 

staged에서 commit을 수행하면 unmodified가 된다

 

 

5) 여러개의 파일을 지정하고 싶을 때

 

공백으로 구분해서 여러개의 파일을 지정할 수 있다

 

예를 들어 a.txt, b.txt, c.txt, d.txt를 모두 생성하고 싶을 때

 

touch a.txt

touch b.txt

touch c.txt

touch d.txt

보다 touch a.txt b.txt c.txt d.txt하면 한번에 생성가능

 

 

 

6) git bash 에디터 탈출하기

 

여러 경우(예: git pull, git commit 등)에 git bash의 에디터로 진입하는데 탈출 못하겠다고 끄지말고

 

예를 들어 git commit만 사용해서 메시지를 쓰지 않으면 강제로 메시지를 쓰라고 에디터로 들어간다

 

 

이런 편집기로 진입하는데 아무것도 안먹혀서 이상한가보다 생각할 수 있다

 

 

insert키를 누른다음에 #위에 아무 commit 메시지를 입력하고

 

 

esc를 누르면 에디터를 나갈 수 있다

 

 

이 상태에서 :wq를 치고 엔터를 누르면 편집기를 나가고

 

 

commit 메시지로 "commit message"를 사용한다는거 확인할 수 있다

 

 

 

7) remote 끊기

 

.git 폴더를 삭제하면 remote 연결을 끊는다

 

 

위와 같이 .git을 삭제하고 git init을 한다음에 다시 push를 해볼려고하면

 

 

 

remote add origin이 안되었다고 에러남

 

 

8) git의 기본 브랜치 변경

 

git의 기본 브랜치는 master로 설정되어 있는데 master / slave라는 주종관계 단어가 논란이 되면서

 

github에서 기본 브랜치명을 main으로 바꿨다고 함

 

그래서 git에서도 기본 branch를 main으로 바꾸고 싶다면

 

git config --global init.defaultBranch main

 

 

global 옵션이라 껐다 켜도 기본적으로 설정되어 있다

 

---------------------------------------

 

어차피 모든걸 알 수 없다

 

필요하면 그때그때 구글링으로 찾아보면 되는것

 

 

참고

 

https://popawaw.tistory.com/138

 

git 의 3가지 작업영역

Git은 내부적으로 크게 3가지 종류의 작업 영역을 두고 동작합니다. 각 작업 영역의 이름은 working directory staging area repository 첫 번째 작업 영역인 working directory는 작업을 하는 프로젝트 디렉토리..

popawaw.tistory.com

 

 

https://novlog.tistory.com/98

 

[Git] #5 깃 버전 관리 VOL3 - 파일의 상태 (tracked untracked unmodified modified staged)

* 다음 포스팅은 깃(Git)의 사용방법에 대하여 정리한 것으로, 개인적인 공부 기록용으로 작성한 글 이기에 잘못된 내용을 포함하고 있을 수 있습니다. * Window 운영체제를 기준으로 작성했습니다.

novlog.tistory.com

 

 

 

https://dev-yakuza.posstree.com/ko/git/default-branch/

 

[Git] 기본 브랜치를 master에서 main으로 설정하기

Git을 사용할 때, 기본 브랜치를 master에서 main으로 변경하는 방법에 대해서 알아봅시다.

dev-yakuza.posstree.com

 

 

https://somjang.tistory.com/entry/Git-fatal-Not-a-valid-object-name-master-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95

 

[Git] fatal: Not a valid object name: 'master'. 해결방법

Git Flow에 대해서 실습을 해보던 중 GitHub에 새로 만든 비어있는 repository를 컴퓨터로 git clone 명령어를 통해 clone해와서 branch를 생성하려고 하니 다음과 같은 오류를 얻었습니다. $ git branch develop..

somjang.tistory.com

 

https://codechacha.com/ko/git-diff/

 

git diff 명령어로 파일 변경 내용 확인

git diff 명령어로 변경사항을 확인할 수 있습니다. `git diff` 명령어는 다음과 같이 unstaged 영역의 변경사항을 출력합니다. `git add .` 명령어를 입력하면 변경 사항이 staging 영역으로 이동하고, unstage

codechacha.com

 

https://dev-yakuza.posstree.com/ko/git/default-branch/

 

[Git] 기본 브랜치를 master에서 main으로 설정하기

Git을 사용할 때, 기본 브랜치를 master에서 main으로 변경하는 방법에 대해서 알아봅시다.

dev-yakuza.posstree.com

 

TAGS.

Comments