git-tag

태그

태그라는걸 알게되서 정리해본다.
(git-scm 에서 내용들을 훑어 보았고, 그곳의 내용으로 정리해본다.)
보통 릴리즈할 때 사용한다고 한다(v1.0, 등등).

태그 조회하기

우선 git tag 명령으로 이미 만들어진 태그가 있는지 확인할 수 있다.

1
2
git tag
v1.0

이 명령은 알파벳 순서로 태그를 보여준다. 사실 순서는 별로 중요한 게 아니다.

검색 패턴을 사용하여 태그를 검색할 수 있다. Git 소스 저장소는 240여 개의 태그가 있다. 만약 1.4.2 버전의 태그들만 검색하고 싶으면 아래와 같이 실행한다.

1
2
3
4
5
git tag -l 'v1.4.2.*'
v1.4.2.1
v1.4.2.2
v1.4.2.3
v1.4.2.4

태그 붙히기

Git의 태그는 Lightweight 태그와 Annotated 태그, 두 종류가 있다. Lightweight 태그는 브랜치와 비슷한데 브랜치처럼 가리키는 지점을 치신 커밋으로 이동시키지 않는다.

단순히 특정 커밋에 대한 포인터일 뿐이다.

한편, Annotated 태그는 Git 데이터베이스에 태그를 만든 사람의 이름, 이메일과 태그를 만든 날짜, 그리고 태그 메시지도 저장한다. 또 GPG(GNU Privacy Guard)로 서명할 수도 있다.

이 모든 정보를 저장해둬야 할 때에만 Annotated 태그를 추천한다.

그냥 다른 정보를 저장하지 않는 단순한 태그가 필요하다면 Lightweight 태그를 사용하는것이 좋다.

Annotated(주석[주해]이 달린) 태그

Annotated 태그를 만드는 방법은 간단하다. tag 명령을 실행할 때 -a 옵션을 추가한다.

1
2
3
git tag -a v1.0 -m "version 1.0"
git tag
v1.0

-m 옵션으로 태그를 저장할 때 메시지를 함께 저장할 수 있다. 명령을 실행할 때 메시지를 이볅하지 않으면 Git은 편집기를 실행시킨다.

git show 명령으로 태그 정보와 커밋 정보를 모두 확인 할 수 있다.

1
2
3
4
5
6
7
8
9
10
git show v1.0
tag v1.0
Tagger: choi sunki <iru@nate.com>
Date: Tue Mar 5 20:46:39 2019 +0900

version 1.0

commit 50ef865abd4bc3fbab66c1e7d4330f6188fcc601 (HEAD -> master, tag: v1.0, origin/master)
Author: choi sunki <iru@nate.com>
Date: Tue Mar 5 19:30:42 2019 +0900

커밋 정보를 보여주기 전에 먼저 태그를 만든사람이 누구인지, 언제 태그를 만들었는지, 그리고 태그 메시지가 무엇인지 보여준다.

태그 공유하기

git push 명령은 자동으로 리모트 서버에 태그를 전송하지 않는다. 태그를 만들었으면 서버에 별도로 Push 해야 한다. 브랜치를 공유하는 것과 같은 방법으로 할 수 있다.

git push origin [태그 이름]을 실행한다.

1
2
3
4
5
6
7
git push origin v1.5
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
Total 44 (delta 18), reused 8 (delta 1)
To git@github.com:schacon/simplegit.git
* [new tag] v1.5 -> v1.5

만약 한 번에 태그를 여러게 Push 하고 싶으면 --tags 옵션을 추가하여 git push 명령을 실행한다. 이 명령으로 리모트 서버에 없는 태그를 모두 전송할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
git push origin --tags
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
Total 44 (delta 18), reused 8 (delta 1)
To git@github.com:schacon/simplegit.git
* [new tag] v0.1 -> v0.1
* [new tag] v1.2 -> v1.2
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
* [new tag] v1.5 -> v1.5

누군가 저장소에서 Clone 하거나 Pull 을 하면 모든 태그 정보도 함께 전송된다.

.gitignore

.gitignore 설정

Git에서 커밋 할때에, 불필요한 파일을 숨겨주고 싶었다.
.gitignore 설정을 하면 된다고 한다.

그리고, ignore 를 모아놓은곳을 찾았다.

맥(MacOs)에서 불필요한 파일 무시(ignore) 하기.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# MacOs
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

윈도우(Windows)에서 불필요한 파일 무시(ignore) 하기.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Windows
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

git 새 줄 문자 경고

git 에서 git add 를 할 때에 아래의 경고를 만났다.

1
2
warning: CRLF will be replaced by LF in index.html.
The file will have its original line endings in your working directory.

경고: CRLF 는 index.html 의 LF로 대체됩니다.
파일은 작업 디렉토리에 원래의 줄 끝을 갖습니다.

CRLF, CR, LF? 이게 뭐지?

찾아보니, 윈도우(Windows)는 CR(Carriage Retrun) 과 LF(Line Feed) 문자를 둘 다 사용하지만, Unix, Linux, MacOSLF 문자만을 사용한다고 한다.
함께 협업하는 인원들이 한 가지 운영체제를 사용한다면 별 문제가 없겠지만, 아닐경우 불편한 문제가 생기는것 같다.
실제로 소스코드의 변함이 없는데, 이 문제로 소스코드가 변경되었다고 판단하는 듯 하다.

더 찾다보니, 위키에서 새줄 문자 라는걸 찾았는데,
CRLF, CR, LF 만 있는게 아니었다(오 머리 아파).

위키 유니코드의 새줄 문자

구분 설명
LF 라인 피드(Line Feed), U+000A
FF 폼 피드(Form Feed), U+000C
CR 캐리지 리턴(Carriage Return), U+000D
CR+LF 연속된 CR과 LF
NEL 다음 줄(Next Line), U+0085
LS 줄 구분자(Line Separator), U+2028
PS 문단 구분자(Paragraph Separator), U+2029

경고문제는 어떻게 해결 하면 좋을까?

뭐 결국은, 어떻게 해야 할까이고..
각각 설정하는 방법도 여기저기서 찾았는데,
나는 각 저장소(repository)별로 속성을 지정해서 설정을 강제하는 방법을 사용하기로 했다.
(같이 협업하는 인원들에게 이건 이렇게 해주시고, 저건 저렇게 해주세요 보다는 훨씬 공수가 덜 들어간다고 생각했다.)

.gitattributes 설정

.gitattributes 파일을 생성하고 아래 내용을 기록한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Auto detect text files and perform LF normalization
# 텍스트 파일 자동 감지 및 LF 정규화 수행
* text=auto

*.cs text diff=csharp
*.java text diff=java
*.html text diff=html
*.css text
*.js text
*.sql text

*.csproj text merge=union
*.sln text merge=union eol=crlf

*.docx diff=astextplain
*.DOCX diff=astextplain

# absolute paths are ok, as are globs
# 절대경로는 괜찮다
/**/postinst* text eol-lf

# paths that don't start with / are treated relative to the .gitattributes folder
# .gitattributes 와 관련하여 /로 시작하지 않는 경로
relative/path/*.txt text eol-lf

참조

git-fatal-refusing-to-merge-unrelated-histories

git pullfatal: refusing to merge unrelated histories

상황

가 PC에서
새로운 저장소(repositories)를 clone하고,
index.html 을 아래와 같이 생성하여 add, commit, push를 했다.

1
Hello, world
1
2
3
git add index.html
git commit -m "Added index.html"
git push

나 PC에서도 새로운 저장소를 clone하고,
폴더를 만들고 예제 파일들을 만들고 있었다.
내가 가 PC에서 푸시했다고 나 PCSJ님에게 알려줬다.
나 PCSJ님은 git pull을 시도했고,
아래와 같이 fatal: refusing to merge unrelated histories라는 문장을 보게 되었고,
git pull이 완료되지 않았다.

1
2
git pull
fatal: refusing to merge unrelated histories

왜 안되는거야?

공식적인 이유는 다음과 같다고 한다.

“git merge” used to allow merging two branches that have no common base by default, which led to a brand new history of an existing project created and then get pulled by an unsuspecting maintainer, which allowed an unnecessary parallel history merged into the existing project. The command has been taught not to allow this by default, with an escape hatch “–allow-unrelated-histories” option to be used in a rare event that merges histories of two projects that started their lives independently

“git merge”는 기본적으로 공통 기반이없는 두 개의 분기를 병합하여 기존 프로젝트의 새로운 히스토리를 작성한 후 예상치 못한 관리자가 가져온 것으로, 불필요한 병행 이력이 기존 프로젝트에 병합되도록 허용하는 데 사용되었습니다 . 이 명령은 기본적으로 허용하지 않도록 배웠습니다. 독립된 삶을 시작한 두 프로젝트의 기록을 병합하는 드문 이벤트에서 탈출 해치 --allow-unrelated-histories 옵션을 사용할 수 있습니다.

이렇게 하자

아래와 같이 하면 git pull이 잘 수행된다.

1
git pull origin <branch> --allow-unrelated-histories

SNS 공유하기

페이스북 공유

콜백이 필요 없다면

1
<a href="http://www.facebook.com/sharer/sharer.php?u=domain.com" target="_blank">페이스북 공유</a>

콜백이 필요하다면

페이스북 앱 아이디가 필요한것 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$('#snsFb').on('click', function(e){

e.preventDefault();

$.ajaxSetup({ cache: true });

$.getScript('//connect.facebook.net/ko_KR/sdk.js', function(){

FB.init({
appId:'your facebook app id',
version: 'v3.2'
});
FB.ui({
method: 'share',
title: '공유 테스트',
description: '공유 테스트를 진행',
href: 'https://daum.net'
}, function(response){
if(response && !response.error_code) {
alert('공유 완료');
} else {
alert('공유 실패');
}
})

});

});

hexo 플러그인 hexo-codepen-v2

codepen 으로 작성한게 있는데,
이걸 hexo 에 올려주는(?) 플러그인(hexo-codepen-v2)이 있어 설치를 해보았다.

blog 폴더로 이동해서,

설치(install)

1
npm install hexo-codepen-v2 --save

사용법(Usage)

1
{% codepen slugHash default_tabs height width userId|anonymous|anon theme %}

CodePen 삽입 코드에서 인수를 얻는 방법

이 코드는 CodePen에서 생성된 것.

1
2
3
4
5
6
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="result" data-user="njean" data-slug-hash="xBKjZE" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="select local">
<span>See the Pen <a href="https://codepen.io/njean/pen/xBKjZE/">
select local</a> by Choi Sunki (<a href="https://codepen.io/njean">@njean</a>)
on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
구분
userId njean
slugHash xBKjZE
theme 0
default_tabs result
height 265
width 이 값은 블로그 테마에 따라 조정되어야 하며 기본적으로 100%

slugHash를 제외한이 설정은 모두 codepen 속성의 _config.yml에서 설정할 수 있다.

1
2
3
4
5
6
codepen:
userId: "njean"
theme: "0"
default_tabs: "js,result"
height: 500
width: "100%"

select 도시별 매장정보 출력

나는, 잘 잃어버리고, 잘 잊어먹는다.
그래서 나중에 혹시 또 쓸일이 있을까봐 남겨둔다.

겨울을 넘어 봄 바람이 올락말락 하는데에,
진행하고 있는 프로젝트에서, 매장정보를 가져올일이 생겼다.
이미 본사에서 사용하고 있는 매장정보 API를 주면, ajax 를 통해 가져오면 되겠지 하고 망연히 있었다.

그런데, 매장정보를 가져오는 부분이 기획서에 없어(out)! 졌더라.
없어졌으니까, “아, 없어졌구나.”라고 중얼 거린후, 다른거 하면서 망연히 있었다.

그렇게 시간은 흐르다가, 갑자기 매장정보를 가져오는게 기획서에 딱!하고 업데이트되어 있었다.

  • 덧붙혀 API를 줄 수 없다! 고 하였다.
  • 그럼 어떻게 해요!? 엑셀문서로! 받았다.

아.. 어떻게 하지?

일단 받은 엑셀 문서를 살펴보았는데,
무지막지하게 많지는 않았지만(음 그래도 음. 음. 음. 음.)..
암튼, 이걸 어떻게 하지?

지역별로 나눠서 어케 해보자 하고 .json형식으로 변환을 했다.

json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
[
{
city: "콩순이시",
items: [
{
code: "kong01",
name: "콩순이 1호점"
},
{
code: "kong02",
name: "콩순이 2호점"
},
]
},
{
city: "빈이시",
items: [
{
code: "bin01",
name: "원빈"
},
{
code: "bin02",
name: "현빈"
},
{
code: "bin03",
name: "조빈"
},
]
},
{
city: "또봇시",
items: [
{
code: "tobot01",
name: "또봇 1호점"
},
{
code: "tobot02",
name: "또봇 2호점"
},
]
},
{
city: "카봇시",
items: [
{
code: "cabot01",
name: "카봇 1호점"
},
{
code: "cabot02",
name: "카봇 2호점"
},
{
code: "cabot03",
name: "카봇 3호점"
},
{
code: "cabot04",
name: "카봇 4호점"
},
]
},
];

stores

그리고, 만든 json형식의 아이를 $scope.stores안에 data 를 만들고 할당해줬다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
$scope.stores = {

// 시도 모델
sidoModel: null,

// 매장 모델
store: {
code: null, // 매장 코드
name: null // 매장 이름
},

// 매장(items) 데이터
sdata: [],

// 지역 및 매장 정보
data: storeData,

// 지역 변경
change: function(){

var local;

$scope.stores.sdata = [];

if( $scope.stores.data[$scope.stores.sidoModel] !== undefined ) {

$scope.stores.sdata = $scope.stores.data[$scope.stores.sidoModel].items;
local = $scope.stores.data[ $scope.stores.sidoModel ].city;

}

},

// 매장명 가져오기
getName: function( store ){

var storeCode = $scope.stores.store.code,
storeName = $.grep( $scope.stores.sdata, function( store ) {
return store.code === storeCode;
});

if( storeName.length > 0 ) {
storeName = storeName[0].name;
}

$scope.stores.store.name = storeName;

}

};

결과 미리보기

timeage.js 사용법

페이스북의 타임라인들을 보노라면, 8분, 4분, 10시간 과 같이 시간을 표시해주는데,
timeago 를 사용하면 이를 쉽게 구현해준다.

CDN

사용법

1. 문서에 timeago.js 포함

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.6.5/jquery.timeago.min.js"></script>

한국어로 표현하고 싶다면, localses 의 jquery.timeago.ko.js를 추가로 포함한다.

1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.6.5/jquery.timeago.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.6.5/locales/jquery.timeago.ko.js"></script>

2. 날짜 넣기

1
2
<!-- 시간은 yyyy-mm-dd hh:ii:ss 형식으로 넣어준다 -->
<time class="tg" datetime="{{시간}}">

3. timeago 초기화

1
2
3
$(document).ready(function(){
$('time.tg').timeago();
});

hexo 를 찾을 수 없다!?

어찌어찌 hexo 를 설치해보았다.

hexo 설치

1
npm install hexo-cli -g

blog init

1
hexo init blog

여기서 문제가 발생해버린다. 다음 내용을 보여주며 안된다.

1
command not found: hexo

hexo 를 찾을수 없다고 나온다.
.bash_profile 에 환경변수 설정을 해보아도 마찬가지.

.zshrc

.zshrc 파일을 열어보니까, 아래와 같은 내용이 보였다.

1
2
3
# Example aliases
# alias zshconfig="mate ~/.zshrc"
# alias ohmyzsh="mate ~/.oh-my-zsh"

그래서 아래와 같이 해봤다.

1
alias hexo="/Users/{{accouts}}/.npm-global/bin/lib/node_modules/hexo-cli/bin/hexo"

오, 잘된다.