<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Tube.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 23 Apr 2023 16:00:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Tube.log</title>
            <url>https://velog.velcdn.com/images/tube-jeonghoon/profile/bf06f918-53c7-4bbd-87a6-745f168dbd46/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Tube.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/tube-jeonghoon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[항해 99 2주차 WIL]]></title>
            <link>https://velog.io/@tube-jeonghoon/%ED%95%AD%ED%95%B4-99-2%EC%A3%BC%EC%B0%A8-WIL</link>
            <guid>https://velog.io/@tube-jeonghoon/%ED%95%AD%ED%95%B4-99-2%EC%A3%BC%EC%B0%A8-WIL</guid>
            <pubDate>Sun, 23 Apr 2023 16:00:43 GMT</pubDate>
            <description><![CDATA[<h1 id="항해-99-2주차-wil">항해 99 2주차 WIL</h1>
<ul>
<li>Virtual DOM</li>
<li>state</li>
<li>props</li>
</ul>
<h2 id="virtual-dom">Virtual DOM</h2>
<p>Virtual DOM은 React에서 사용되는 개념으로, 실제 브라우저에 그려지는 DOM과는 별개로 메모리 상에 존재하는 가상의 DOM입니다.</p>
<p><code>DOM</code>은 Document Object Model의 약어로, 웹브라우저는 <code>DOM</code>을 활용하여 객체에 자바스크립트와 CSS를 적용합니다.</p>
<p><code>DOM</code>은 트리형태라서 특정 노드를 찾거나 수정하거나 제거하거나 원하는 곳에 삽입 가능합니다. 하지만 동적 UI에 최적화되어 있지 않아서, 복잡한 UI 상태 변화에 따른 DOM 처리는 성능 저하를 초래합니다. 이러한 문제를 해결하기 위해 React에서는 Virtual DOM 방식을 사용하여 DOM 업데이트를 추상화하고, DOM 처리 횟수를 최소화하여 효율적으로 처리합니다.</p>
<p>즉, Virtual DOM은 상태가 업데이트될 때마다 새로운 가상 DOM을 생성하고 변경된 부분만 감지하여 실제 DOM을 업데이트하므로, 전체 페이지를 다시 렌더링하지 않고도 업데이트가 가능합니다. 이러한 Virtual DOM의 장점은 React의 성능 향상 뿐 아니라, 코드의 유지 보수성도 높여줍니다.
<img src="https://velog.velcdn.com/images/tube-jeonghoon/post/af99152f-d9fa-4b72-9c4a-dad5e8ab3e46/image.jpg" alt=""></p>
<h2 id="state">State</h2>
<p>리액트에서 변수를 저장하고자 할 때, <strong><code>useState</code></strong> 훅을 사용하여 상태(state)를 관리합니다. 이 훅은 첫 번째 원소로 상태 값(state value)을, 두 번째 원소로 상태 값을 변경하는 함수(setState function)를 반환합니다. 상태값이 갱신될 때마다 리렌더링되어 화면이 갱신됩니다.</p>
<p><strong><code>state</code></strong>는 리액트에서 변수와 같은 존재로, <strong><code>const [age, setAge]</code></strong>와 같은 방식으로 변수를 정의하고 값을 초기화할 수 있습니다. 이 때 <strong><code>setAge</code></strong>는 <strong><code>age</code></strong>의 값을 변경할 때 사용하는 함수로, 내부적으로 필요한 프로세스를 실행하며 <strong><code>age</code></strong>의 값을 갱신합니다.</p>
<p>예를 들어, <strong><code>setAge(30)</code></strong>과 같은 방법으로 <strong><code>age</code></strong>의 값을 변경할 수 있습니다. 이러한 상태 관리를 통해, 컴포넌트 내에서 변화하는 값을 저장하고 사용할 수 있게 됩니다.</p>
<p>아래는 예시 코드입니다.</p>
<pre><code class="language-jsx">import React, { useState } from &quot;react&quot;;

function Example() {
  // age 변수의 초기값을 0으로 설정하고, setAge 함수를 사용하여 age 값을 변경할 수 있도록 함
  const [age, setAge] = useState(0);

  const handleAgeChange = () =&gt; {
    setAge(age + 1); // 버튼 클릭 시 age의 값을 1 증가시키도록 함
  };

  return (
    &lt;div&gt;
      &lt;p&gt;저의 나이는 {age}살 입니다.&lt;/p&gt;
      &lt;button onClick={handleAgeChange}&gt;나이 추가&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p>위 코드에서 <strong><code>useState</code></strong>를 사용하여 age 변수와 setAge 함수를 생성했습니다. age 변수는 현재 0으로 초기화되어 있으며, <strong><code>setAge</code></strong>함수를 사용하여 값을 변경할 수 있습니다. 이 함수를 호출하면 인자로 전달된 값이 age 변수에 할당되어 값을 갱신하고, 해당 컴포넌트를 리렌더링합니다.</p>
<p><strong><code>handleAgeChange</code></strong> 함수에서는 <strong><code>setAge</code></strong> 함수를 호출하여 age 값을 1 증가시키도록 했습니다. 이 함수는 버튼 클릭 시 호출되며, 해당 컴포넌트를 리렌더링합니다.</p>
<p>위 코드를 실행하면 화면에 &quot;저의 나이는 0살 입니다.&quot;와 &quot;나이 추가&quot; 버튼이 보입니다. 버튼을 클릭할 때마다 나이가 1씩 증가하며, 화면에 표시됩니다. 이처럼, useState를 사용하여 상태(state)를 관리하면 컴포넌트의 상태를 관리하고, 화면에 동적인 변화를 표시할 수 있습니다.</p>
<h2 id="props">Props</h2>
<ul>
<li>props는 React에서 컴포넌트 간 데이터를 전달하는데 사용되는 속성입니다.</li>
<li>부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하려면, 부모 컴포넌트에서 자식 컴포넌트를 사용할 때, 속성으로 전달합니다. 이때, 전달하는 데이터는 객체 형태이며, 자식 컴포넌트 내부에서는 해당 데이터를 props라는 이름으로 사용합니다.</li>
</ul>
<pre><code class="language-jsx">import React from &#39;react&#39;;

function Hello(props) {
  return (
    &lt;div&gt;
      &lt;p&gt;Hello, {props.name}!&lt;/p&gt;
      &lt;p&gt;{props.message}&lt;/p&gt;
    &lt;/div&gt;
  );
}

function App() {
  return (
    &lt;div&gt;
      &lt;Hello name=&quot;React&quot; message=&quot;Welcome to React World!&quot; /&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<p>위 코드에서 <code>Hello</code>컴포넌트에서 <code>props</code>를 사용하여 전달받은 데이터를 출력하고 있습니다. <strong><code>name</code></strong>과 <strong><code>message</code></strong>는 부모 컴포넌트인 <strong><code>App</code></strong> 컴포넌트에서 자식 컴포넌트인 <strong><code>Hello</code></strong> 컴포넌트로 전달한 데이터입니다. 이렇게 전달받은 데이터를 <strong><code>props</code></strong>를 통해 사용할 수 있습니다.)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[항해 99 1주차 WIL]]></title>
            <link>https://velog.io/@tube-jeonghoon/%ED%95%AD%ED%95%B4-99-1%EC%A3%BC%EC%B0%A8-WIL</link>
            <guid>https://velog.io/@tube-jeonghoon/%ED%95%AD%ED%95%B4-99-1%EC%A3%BC%EC%B0%A8-WIL</guid>
            <pubDate>Sun, 23 Apr 2023 15:55:57 GMT</pubDate>
            <description><![CDATA[<h1 id="항해-99-1주차-wil">항해 99 1주차 WIL</h1>
<ul>
<li>ES6란?</li>
<li>ES5/ES6 문법 차이</li>
</ul>
<h2 id="es6란">ES6란?</h2>
<p>ECMAScript 6(ES6)은 JavaScript 버전 중 하나입니다. 2015년에 도입되었으며 언어에 많은 새로운 기능을 도입하여 개발자가 코드를 더 쉽고 효율적으로 작성할 수 있도록 했습니다.</p>
<p>대표적으로 추가된 새로운 기능으로는 let, const, 화살표함수, 템플릿 리터럴, 클래스, rest 및 spread연산자가 있습니다.</p>
<h3 id="let-및-const">let 및 const</h3>
<p>이전 ES5문법에서는 <code>var</code>의 키워드를 이용했습니다. var에는 문제점이 많았는데 let, const 키워드가 새로이 나와 <code>var</code>를 대체하였습니다.</p>
<h3 id="var-">var ?</h3>
<p><code>var</code>키워드는 변수를 선언하는 데 사용됩니다. 변수에 값을 할당하거나 값을 할당하지 않고 변수를 선언하는 데 사용됩니다. 하지만 단점이 많습니다. 크게 두가지 단점으로는 함수 범위 액세스, 호이스팅 입니다.</p>
<ul>
<li><p>블록 범위가 아니라 함수 범위에 있다는 것</p>
<p>  함수 내의 for문이나 if문 내에 생성 된 변수가 함수 내에만 있으면 사용가능하다는 점입니다.</p>
</li>
<li><p>호이스팅을 허용한다는 점</p>
<p>  var로 선언된 위치에 관계없이 해당 범위의 맨 위로 이동 됩니다.</p>
</li>
</ul>
<h3 id="화살표-함수">화살표 함수</h3>
<p><code>Arrow function</code> 은 함수 표현식을 작성하기 이후 보다 간결한 구문을 제공하는 기능입니다. 기본 형식은 <code>let function = (매개변수) ⇒ 결과값</code> 입니다. 기존 함수 표현식에 비해 몇가지 장점이 있습니다.</p>
<pre><code class="language-jsx">let add = (x, y) =&gt; {
    return x+y;
}</code></pre>
<blockquote>
<p>🔥 고유한 this 컨텍스트가 없습니다. 대신 주변 코드에서 this 컨텍스트를 상속합니다. 또한 new 키워드와 함께 생성자로 사용할 수 없습니다.</p>
</blockquote>
<h3 id="템플릿-리터럴">템플릿 리터럴</h3>
<p>템플릿 리터럴은 JavaScript에서 변수나 표현식을 포함할 수 있는 문자열을 만드는 방법입니다. </p>
<pre><code class="language-jsx">const name = &#39;tube&#39;;
const message = `Hello ${name}`;</code></pre>
<blockquote>
<p>템플릿 리터럴은 변수나 표현식을 포함할 수 있는 동적 문자열을 쉽게 만들 수 있기 때문에 JavaScript의 유용한 기능입니다. 또한 <code>+</code>연산자로 문자열을 연결하는 것보다 더 읽기 쉽습니다.</p>
</blockquote>
<h3 id="클래스">클래스</h3>
<p>es6에는 클래스가 추가 되었습니다.  클래스는 객체 생성을 위한 틀입니다. 생성된 모든 개체가 갖게 될 속성과 동작을 정의합니다.</p>
<pre><code class="language-jsx">// 클래스 생성
class Person {
  constructor(name, species) {
    this.name = name;
    this.gender = gender;
  }

  speak() {
    console.log(`안녕 내이름은 ${this.name}이야! 내 성별은 ${this.gender}야`);
  }
}

// 클래스를 사용하여 개체 생성
const tube = new Person(&quot;tube&quot;, &quot;남자&quot;);
tube.speak(); // 안녕 내 이름은 tube이야! 내 성별은 남자야</code></pre>
<h3 id="spread-연산자">spread 연산자</h3>
<p>배열이나 객체를 다른 배열이나 객체로 확장하거나 병합할 때 유용하게 사용할 수 있는 문법입니다. 전개 구문은 <code>...</code> 연산자를 사용하여 표현하며, 배열 또는 객체의 요소나 속성을 개별적으로 추출하여 다른 배열이나 객체에 포함시킬 수 있습니다.</p>
<pre><code class="language-jsx">// 배열에 값 추가하기
let arr = [1, 2, 3]
let newArr = [...arr, 4]
console.log(newArr) // [1,2,3,4]

// 배열 합치기
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// 배열 복사하기
const arr4 = [1, 2, 3];
const arr5 = [...arr1]; // [1, 2, 3]

// 다른객체에 추가하기
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const obj3 = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
</code></pre>
<h3 id="나머지-매개변수-rest-parameter">나머지 매개변수 (rest parameter)</h3>
<p>함수 정의에서 사용되는 선언으로서, 함수 호출 시 전달된 인수를 배열로 나타낼 수 있게 합니다. 나머지 매개변수는 함수의 마지막 매개변수로 선언되어야 하며, 선언 시 매개변수 이름 앞에 <strong><code>...</code></strong>를 붙입니다.</p>
<pre><code class="language-jsx">// 나머지 매개변수
function exampleFunc(a, b, c, ...args) {
  console.log(a, b, c); // 1, 2, 3
  console.log(...args); // 4, 5
  console.log(args); // [4, 5]
}

exampleFunc(1, 2, 3, 4, 5);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[k9s]]></title>
            <link>https://velog.io/@tube-jeonghoon/k9s</link>
            <guid>https://velog.io/@tube-jeonghoon/k9s</guid>
            <pubDate>Thu, 22 Sep 2022 05:25:15 GMT</pubDate>
            <description><![CDATA[<p>#kubernetes</p>
<h1 id="k9s">k9s</h1>
<p><code>K9s</code>는 Kubernetes 클러스터와 상호 작용하는 터미널 기반 UI입니다. <code>k9s</code> 는 배포 된 어플리케이션을 탐색, 관찰 및 관리 합니다.</p>
<h2 id="설치">설치</h2>
<h3 id="macos">macos</h3>
<pre><code class="language-bash"># via Homebrew
brew install derailed/k9s/k9s</code></pre>
<h3 id="linux">linux</h3>
<pre><code class="language-bash">brew install derailed/k9s/k9s</code></pre>
<h3 id="windows">windows</h3>
<pre><code class="language-powershell"># Via scoop
scoop install k9s

# Via chocolatey
choco install k9s</code></pre>
<h2 id="명령어">명령어</h2>
<h3 id="cli">CLI</h3>
<pre><code class="language-bash"># 사용 가능한 모든 CLI 옵션 나열
k9s help

# k9s 런타임(로그, 구성 등)에 대한 정보
k9s info

# 주어진 네임스페이스에서 k9을 실행합니다.
k9s -n mynamespace

# pod명령을 통해 k9s를 실행하고 pod보기에서 실행합니다.
k9s -c pod</code></pre>
<h3 id="keybinding">Keybinding</h3>
<ul>
<li><code>?</code>: 도움말 나열</li>
<li><code>ctrl + a</code>: 클러스터에서 사용가능한 리소스 나열</li>
<li><code>:q</code>, <code>ctrl + c</code>: k9s 종료</li>
<li><code>:po</code>: 짧은 명령어(별칭)으로 리소스 보기 (:po pod보기, :svc 서비스 보기, :ns 네임스페이스보기)</li>
<li><code>:po &lt;namespace&gt;</code>: 해당 네임스페이스에서 리소스보기</li>
<li><code>l</code>: 로그 확인하기 (logs)</li>
<li><code>d</code>: 상세설명 보기 (describe)</li>
<li><code>e</code>: 편집하기 (edit)</li>
<li><code>ctrl + d</code>: 리소스 삭제 (실제 리소스 지워집니다.)</li>
<li><code>ctrl + k</code>: 리소스 삭제 (force)</li>
<li><code>ctrl-w</code>: 넓은열 (kubectl ... -o wide)</li>
<li><code>ctrl-z</code>: 오류 상태인 리소스 보기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vim 사용하기]]></title>
            <link>https://velog.io/@tube-jeonghoon/Vim-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@tube-jeonghoon/Vim-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 23 Mar 2022 01:10:41 GMT</pubDate>
            <description><![CDATA[<h1 id="vim-사용하기">Vim 사용하기</h1>
<p>맨날 Terminal 안의 문서 수정 용도로만 사용하던 <code>vim</code> 이것을 이용하면 생산성이 좋아진다고 한다. 한번 배워서 써볼까 한다.</p>
<blockquote>
<p>저장소 <a href="https://github.com/vim/vim">https://github.com/vim/vim</a></p>
</blockquote>
<h2 id="vim">Vim</h2>
<p><code>Vim</code>은 &quot;Vi Improved&quot; 의 약자로 vi 호환 텍스트 편집기이다. CUI용 Vim과 GUI용 gVim이 있다. Vim은 Vi와 호환되면서도 독자적으로 다양한 기능을 추가하여 편의를 돕고 있다.</p>
<h2 id="번외-neovim">번외 Neovim</h2>
<p><code>Neovim</code>은  Vim의 확대집합이 되는 Vim의 리팩터 판이라고 한다. 동일한 구성을 공유 한다고 하니 한번 써봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript로 하는 알고리즘]]></title>
            <link>https://velog.io/@tube-jeonghoon/Javascript%EB%A1%9C-%ED%95%98%EB%8A%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@tube-jeonghoon/Javascript%EB%A1%9C-%ED%95%98%EB%8A%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Mon, 22 Nov 2021 05:38:14 GMT</pubDate>
            <description><![CDATA[<p>javacript로 알고리즘 문제를 하루에 하나씩 풀어보려고 한다.
유명 알고리즘 사이트로는</p>
<ul>
<li>백준 온라인 저지 (<a href="https://www.acmicpc.net/">https://www.acmicpc.net/</a>)</li>
<li>알고스팟 (<a href="https://algospot.com/">https://algospot.com/</a>)</li>
<li>프로그래머스(<a href="https://programmers.co.kr/">https://programmers.co.kr/</a>)
등이 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git 사용법 (2)]]></title>
            <link>https://velog.io/@tube-jeonghoon/Git-%EC%82%AC%EC%9A%A9%EB%B2%952</link>
            <guid>https://velog.io/@tube-jeonghoon/Git-%EC%82%AC%EC%9A%A9%EB%B2%952</guid>
            <pubDate>Thu, 29 Apr 2021 21:17:06 GMT</pubDate>
            <description><![CDATA[<h2 id="git-브랜치">Git 브랜치</h2>
<p>모든 버전 관리 시스템은 브랜치를 지원한다. 원래 코드와 상관없이 독립적으로 개발을 진행할 수 있어야 되는데, 이렇게 사용하는 것이 브랜치이다.
다른 브랜치를 만들어 작업한 다음 나중에 병합(merge) 하는 식으로 작업을 권장한다.</p>
<h3 id="브랜치-생성하기--git-branch-">브랜치 생성하기 ( git branch )</h3>
<p>git의 새 브런치는 <code>git branch</code>명령어로 만들 수 있다.</p>
<pre><code class="language-bash">$ git branch tube</code></pre>
<p>git은 HEAD라는 특수한 포인터가 지금 작업 중인 브랜치를 파악한다.</p>
<p>브랜치를 생성하면서 바로 해당 브랜치로 이동할 수 있다.</p>
<pre><code class="language-bash">$ git switch -c tube</code></pre>
<h3 id="브랜치-이동하기--git-switch-">브랜치 이동하기 ( git switch )</h3>
<p><code>git switch</code>명령어로 HEAD가 가리키는 브랜치를 변경할 수 있다.</p>
<pre><code class="language-bash">$ git switch tube
Switched to branch &#39;tube&#39;</code></pre>
<p><strong>git 2.3 이후 버전에서는 checkout 기능 중에 switch, restore 기능은 분리되었다. checkout 명령어가 안되는 건 아니지만 checkout의 기능이 많아 분리 시킨 듯싶다.</strong></p>
<p>tube 브랜치로 파일을 하나 만들고 커밋 해 보자. ( 현재 tube의 브랜치이다. )</p>
<pre><code class="language-bash">$ echo &quot;tube branch&quot; &gt; REAMDME_TUBE.md 
$ git add .
$ git commit -m &quot;tube branch commit&quot;
$ ll
total 16
drwxr-xr-x   5 jeonjeonghoon  staff   160B  4 29 03:36 .
drwxr-xr-x   8 jeonjeonghoon  staff   256B  4 29 03:25 ..
drwxr-xr-x  12 jeonjeonghoon  staff   384B  4 29 03:36 .git
-rw-r--r--   1 jeonjeonghoon  staff    12B  4 29 03:27 README.md
-rw-r--r--   1 jeonjeonghoon  staff    12B  4 29 03:36 REAMDME_TUBE.md</code></pre>
<p>잘 생성 되었다. 그럼 이제 다시 master의 브랜치로 가보자.</p>
<pre><code class="language-bash">$ get switch master
$ ll
total 8
drwxr-xr-x   4 jeonjeonghoon  staff   128B  4 29 03:36 .
drwxr-xr-x   8 jeonjeonghoon  staff   256B  4 29 03:25 ..
drwxr-xr-x  12 jeonjeonghoon  staff   384B  4 29 03:36 .git
-rw-r--r--   1 jeonjeonghoon  staff    12B  4 29 03:27 README.md</code></pre>
<p>tube 브랜치에서 커밋 했던 파일이 없다. 두 브랜치의 작업은 독립적으로 각 브랜치에 존재한다. 때가 되면 각자 작업 후 병합(merge) 해줘야 된다.</p>
<h4 id="현재-포인터head-가르키고-있는-브랜치-확인하기">현재 포인터(HEAD) 가르키고 있는 브랜치 확인하기</h4>
<p>현재 어떤 브랜치에서 작업 중인지 확인해야 될 때가 있다. <code>git log</code>명령어로 확인하도록 하자.</p>
<pre><code class="language-bash">$ git log --oneline --decorate --graph --all
* 7ec78d8 (HEAD -&gt; tube) tube branch commit
* 373147d (master) first commit
(END)</code></pre>
<h3 id="브랜치-merge-하기">브랜치 merge 하기</h3>
<p>새로운 브랜치를 만들어 작업이 끝났거나 이슈를 해결했으면 <code>git merge</code>명령어로 다시 브랜치를 합쳐야 한다.
밑은 12번 issue가 생겨 브랜치를 만들어 해결하는 과정이다.</p>
<pre><code class="language-bash">$ git switch -c iss12
$ echo &quot;fixed me&quot; &gt; fixedfile.md
$ git add fixedfile.md
$ git commit -m &quot;fixed the issue 12&quot;
$ git switch master
$ git merge iss12</code></pre>
<h3 id="브랜치-삭제하기">브랜치 삭제하기</h3>
<p>더 이상 필요 없는 브랜치는 <code>git branch -d</code>명령어로 삭제해 준다.</p>
<pre><code class="language-bash">$ git branch -d iss12</code></pre>
<h3 id="브랜치-관리하기">브랜치 관리하기</h3>
<p><code>git branch</code>명령어로 branch들을 관리할 수 있다. <code>git branch -v</code>명령어를 이용하면 각 브랜치마다 마지막 커밋 메시지를 볼 수 있다.</p>
<pre><code class="language-bash">$ git branch -v</code></pre>
<p><code>--merged</code> <code>--no-merged</code>옵션을 이용하면 merge된 브랜치와 merge 되지 않은 브랜치를 볼 수 있다.</p>
<pre><code class="language-bash">$ git branch --merged
$ git branch --no-merged</code></pre>
<p><strong>merge 되지 않는 커밋을 담고 있는 브랜치는 기본적으로 삭제되지 않지만 git branch -D 명령어로 강제로 삭제할 수 있다.</strong></p>
<h2 id="리모트-브랜치">리모트 브랜치</h2>
<p><strong>리모트 Refs</strong>는 리모트 저장소에 있는 포인터인 레퍼런스이다. 리모트 저장소에 있는 브랜치, 태그 등등을 의미한다. <code>git ls-remote</code>로 모든 리모트 Refs를 조회할 수 있다. <code>git remote show</code>명령은 모든 리모트 브랜치와 그 정보를 보여준다.</p>
<pre><code class="language-bash">$ git remote show
origin

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/tube-jeonghoon/git-test.git
  Push  URL: https://github.com/tube-jeonghoon/git-test.git
  HEAD branch: master
  Remote branches:
    master                        tracked
    refs/remotes/origin/serverfix stale (use &#39;git remote prune&#39; to remove)
  Local ref configured for &#39;git push&#39;:
    master pushes to master (fast-forwardable)</code></pre>
<h3 id="리모트-트래킹-브랜치">리모트 트래킹 브랜치</h3>
<p>리모트 브랜치를 추적하는 브랜치이다. 이 브랜치는 로컬에 있지만 움직일 수는 없다. 리모트 서버에 연결할 때마다 리모트 브랜치에 따라서 자동으로 움직일 뿐이다. 리모트 트래킹 브랜치는 <strong>북마크</strong>라고 할 수 있다.</p>
<p>리모트 브랜치의 이름은 <code>(remote)/(branch)</code> 형식으로 되어 있다. 예를 들어 저장소 origin의 master의 브랜치를 보고 싶다면 origin/master라는 이름으로 브랜치를 확인하면 된다.</p>
<h3 id="브랜치-원격저장소로-푸시하기--git-push-">브랜치 원격저장소로 푸시하기 ( git push )</h3>
<p>로컬 브랜치를 서버로 전송하려면 쓰기 권한이 있는 리모트 저장소에 Push 해야 한다.
<code>git push (remote) (branch)</code>명령어로 원격 저장소에 Push 할 수 있다.</p>
<pre><code class="language-bash">$ git push origin hotfix</code></pre>
<p><code>git push origin hotfix</code>명령어는 자동적으로 원격 저장소에 hotfix 브랜치에 저장된다. [로컬 저장소]:[원격 저장소] 형으로 자동으로 변형된다. 만약 원격 저장소에 다른 이름의 브랜치로 저장하고 싶으면 [원격 저장소]의 이름을 바꿔주면 된다. <code>git push origin hotfix:newhotfix</code> 이런 형태로 말이다.</p>
<h3 id="브랜치-원격저장소에서-패치하기--git-fetch-">브랜치 원격저장소에서 패치하기 ( git fetch )</h3>
<p>업데이트된 원격 저장소에서 데이터를 받을 때는 <code>git fetch</code> 명령어를 쓰면 된다. 주의할 점은 여기서 Fetch 명령으로 <strong>리모트 트래킹 브랜치를 내려받는다고 해서 로컬 저장소에 수정할 수 있는 새로운 브랜치가 생기는 것</strong>이 아니다. 그냥 origin에 해당 브랜치의 <strong>리모트 브랜치 포인터</strong>가 생기는 것이다.
내려받은 Fetch에는 두 가지 선택지가 있다.</p>
<ol>
<li><code>git merge [remote]/[branch]</code>로 받은 내용하고 병합(merge) 하는 것<pre><code class="language-bash">$ git merge origin/hotfix</code></pre>
</li>
</ol>
<p>2.<code>git switch -c [new_branch] [remote]/[branch]</code>로 병합(merge) 하지 않고 트래킹 브랜치에서 새 브랜치를 만들어서 작업하는 것</p>
<pre><code class="language-bash">$ git switch -c hotfix origin/hotfix</code></pre>
<h3 id="리모트-브랜치-추적하기">리모트 브랜치 추적하기</h3>
<h4 id="트래킹-브랜치-만들기--git-switch--c-net_branch-remotenamebranch-">트래킹 브랜치 만들기 ( git switch -c [net_branch] [remotename]/[branch] )</h4>
<p>리모트 트래킹 브랜치를 로컬 브랜치로 받아오면 자동으로 &quot;tracking 브랜치&quot;가 만들어진다. 트래킹 브랜치는 리모트 브랜치와 직접적인 연결고리가 있는 로컬 브랜치이다. 저장소를 clone 하면 자동적으로 로컬 master 브랜치를 리모트 origin/master 브랜치의 트래킹 브랜치로 만든다.</p>
<p>새로운 브랜치를 생성하면서 origin 저장소의 hotfix 브랜치를 트래킹 한다.</p>
<pre><code class="language-bash">$ git switch -c hf origin/hotfix</code></pre>
<p>기존 브랜치에 origin 저장소의 hotfix 브랜치를 트래킹한다.</p>
<pre><code class="language-bash">$ git switch hotfix
$ git brach -u origin/hotfix</code></pre>
<h4 id="트래킹-브랜치-업데이트--git-pull-">트래킹 브랜치 업데이트 ( git pull )</h4>
<p>해당 리모트 브랜치가 업데이트되면 <code>git pull</code> 명령어로 업데이트하면 된다.</p>
<pre><code class="language-bash">$ git pull</code></pre>
<h3 id="리모트-브랜치-삭제--git-push-remote---delete-remotebranch">리모트 브랜치 삭제 ( git push [remote] --delete [remotebranch]</h3>
<p>해당 리모트 브랜치가 필요 없어지면 <code>git push --delete</code>명령어로 삭제해 준다.</p>
<pre><code class="language-bash">$ git push origin --delete hotfix
To https://github.com/tube-jeonghoon/git-test.git
 - [deleted]         hotfix</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git 사용법 (1)]]></title>
            <link>https://velog.io/@tube-jeonghoon/git-%EC%82%AC%EC%9A%A9%EB%B2%951</link>
            <guid>https://velog.io/@tube-jeonghoon/git-%EC%82%AC%EC%9A%A9%EB%B2%951</guid>
            <pubDate>Thu, 29 Apr 2021 21:15:51 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<p>git은 소스 코드 관리를 위한 분산 버전 관리 시스템이다.</p>
<h2 id="설치">설치</h2>
<h3 id="windows">windows</h3>
<p><a href="https://git-scm.com/download/win">windows_git</a> 해당 사이트 접속 시 자동으로 다운 받아지며 안 받아지면 수동으로 32bit(x86) 64bit(x64)에 맞춰서 다운로드해 주자</p>
<h3 id="debian-or-fedora">Debian or Fedora</h3>
<p>패키지 관리 도구를 이용하여 설치한다.
<strong>Fedora</strong></p>
<pre><code class="language-bash">$ sudo yum install git</code></pre>
<p><strong>Debian</strong></p>
<pre><code class="language-bash">$ sudo apt-get install git</code></pre>
<h3 id="mac">Mac</h3>
<p>Mac은 Mac 패키지 관리자인 <code>homebrew</code>로 설치하는 게 업데이트나 관리 면에서 유용하다.</p>
<pre><code class="language-bash">$ brew install git</code></pre>
<h2 id="버전-업데이트">버전 업데이트</h2>
<p>현재 글을 쓰고 있는 버전은 <code>2.31.1</code>이다.
Ubuntu나 Windows10에는 기본적으로 git이 깔리지만 낮은 버전으로 깔린다. 2.3 버전 이후로 명령어의 변화가 있으니 업데이트해주도록 하자.</p>
<pre><code class="language-bash">$ sudo add-apt-repository ppa:git-core/ppa -y
$ sudo apt-get update
$ sudo apt-get install git -y
$ git --version
2.31.1</code></pre>
<h2 id="최초-설정">최초 설정</h2>
<h3 id="git-config">git config</h3>
<p><code>git config</code>라는 도구로 설정 내용을 확인하고 변경할 수 있다. Git은 이 설정에 따라 동작한다.</p>
<ol>
<li>/etc/gitconfig: 시스템의 모든 사용자와 모든 저장소에 적용되는 설정이다.</li>
<li>~/.gitconfig, ~/.config/git/config: 해당 사용자에게만 적용되는 설정이다.</li>
<li>.git/config: 특정 저장소 내에서만 적용된다.
해당 적용순서는 3 -&gt; 2 -&gt; 1 순서로 우선 적용된다.</li>
</ol>
<h3 id="사용자-정보-업데이트">사용자 정보 업데이트</h3>
<p>사용자 이름과 이메일 주소를 불러와서 적용한다. git은 <code>commit</code>을 할 때마다 이 정보를 사용한다.
한번 <code>commit</code>후에는 변경 불가능하다.</p>
<pre><code class="language-bash">$ git config --global user.name &quot;tube-jeonghoon&quot;
$ git config --global user.email &quot;tube@abc.com&quot;</code></pre>
<p>프로젝트마다 다른 이름과 이메일 주소를 사용하고 싶으면 <code>--global</code> 옵션을 빼준다.</p>
<h2 id="git-저장소-만들기">Git 저장소 만들기</h2>
<h3 id="새로운-git-저장소-만들기--git-init-">새로운 git 저장소 만들기 ( git init )</h3>
<p>해당 명령어로 git 저장소를 만들어준다. </p>
<pre><code class="language-bash">$ git init</code></pre>
<p>이 명령은 <code>.git</code>에 대한 하위 디렉터리가 있는 디렉터리인 Git저장소를 만든다. <code>.git</code>디렉터리에는 저장소에 필요한 파일이 들어있다.</p>
<h3 id="기존-git-저장소를-clone-하기--git-clone-">기존 git 저장소를 clone 하기 ( git clone )</h3>
<p>다른 프로젝트에 참여하거나 이미 만들어진 git 저장소를 복사하고 싶을 때 <code>git clone</code>이라는 명령어를 사용한다
<code>git clone</code>을 사용하면 git history까지 모두 복사해서 온다.</p>
<pre><code class="language-bash">$ git clone https://github.com/tube-jeonghoon/tube-jeonghoon.git</code></pre>
<h2 id="로컬-저장소에-저장하기">로컬 저장소에 저장하기</h2>
<p>워킹 디렉터리의 모든 파일은 크게 <code>Tracked</code>와 <code>Untracked</code>로 나뉘어진다. <code>Tracked</code>파일은 또  <code>Unmodified</code>와 <code>Modified</code>및 <code>Staged</code>로 나뉘어진다.</p>
<h3 id="파일-상태-확인하기--git-status-">파일 상태 확인하기 ( git status )</h3>
<p><code>git status</code>명령어를 사용한다.</p>
<pre><code class="language-bash">$ git status
$ git status -s</code></pre>
<p><code>git status -s</code> 의 -s 옵션은 현재 파일 상태의 간략하게 보여준다.</p>
<h3 id="파일을-추적하기--git-add-">파일을 추적하기 ( git add )</h3>
<p><code>git add</code>명령어로 git이 파일을 새로 추적할 수 있다.</p>
<pre><code class="language-bash">$ git add README.md</code></pre>
<p>git add (file) 명령어를 통해 디렉터리에 있는 파일을 추적하고 관리하도록한다. git add 명령은 파일 또는 디렉터리의 경로를 argument로 받는다. 디렉터리면 아래에 있는 모든 파일을 추적한다.</p>
<h3 id="modified-상태의-파일을-stage-하기--git-add-">Modified 상태의 파일을 Stage 하기 ( git add )</h3>
<p>파일 수정 후 git에 추가해보자
첫 번째 유형은</p>
<pre><code class="language-bash">$ git status
On branch master
Changes to be committed:
  (use &quot;git reset HEAD &lt;file&gt;...&quot; to unstage)
    new file:   README.md

Changes not staged for commit:
  (use &quot;git add &lt;file&gt;...&quot; to update what will be committed)
  (use &quot;git checkout -- &lt;file&gt;...&quot; to discard changes in working directory)
    modified:   TEST.md

$ git add TEST.md
$ git status
On branch master
Changes to be committed:
  (use &quot;git restore --staged &lt;file&gt;...&quot; to unstage)
    new file:   README.md
    modified:   TEST.md</code></pre>
<p>보통 <code>Tracked</code>의 파일을 수정하게 되면 &quot;Changes not staged for commit&quot; 상태가 된다. 수정 한 파일이 <code>Tracked</code>상태이지만 아직 <code>Staged</code>상태는 아니라는 것이다. <code>git add</code>명령어로 파일을 다시 추적할 수 있다.</p>
<p><code>git add</code>는 세 가지 상황에서 쓸 수 있다.</p>
<ol>
<li>파일을 새로 추적할 때</li>
<li>수정한 파일을 <code>Staged</code>상태로 만들 때</li>
<li><code>Merge</code>할 때 충돌 난 상태의 파일을 Resolve 상태로 만들 때</li>
</ol>
<h3 id="staged와-unstaged-상태의-변경-내용-보기--git-diff-">Staged와 Unstaged 상태의 변경 내용 보기 ( git diff )</h3>
<p>어떤 내용이 변경되었는지 확인하려면 <code>git diff</code>명령어를 사용해야 한다.
다음은 <code>Tracked</code>된 파일을 수정해서 <code>Staged</code>와 <code>Unstaged</code> 상태 모두 가진 상태이다.</p>
<pre><code class="language-bash">$ git status
On branch master

No commits yet

Changes to be committed:
  (use &quot;git rm --cached &lt;file&gt;...&quot; to unstage)
    new file:   README.md

Changes not staged for commit:
  (use &quot;git add &lt;file&gt;...&quot; to update what will be committed)
  (use &quot;git restore &lt;file&gt;...&quot; to discard changes in working directory)
    modified:   README.md</code></pre>
<p>이 상태에서 <code>git commit</code>을 하게 되면 수정되지 않은 README.md가 commit 될 것이다.
무엇이 달라졌는지 확인하자.</p>
<pre><code class="language-bash">$ git diff
diff --git a/README.md b/README.md
index 264dee5..d214cf8 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
 wow!
+wow2
(END)</code></pre>
<p>wow2 라는 구문이 추가된 걸 볼 수 있다. 하지만 <code>git add</code> 다시 staged 상태로 만들지 않으면 wow2라는 구문은 <code>commit</code> 되지 않는다. 수정 한 파일을 모두 <code>git add</code>로 모두 staged 상태로 만들었다면 <code>git diff</code>명령은 아무것도 출력하지 않는다.</p>
<h3 id="staged-상태-생략하기--git-commit--a-">Staged 상태 생략하기 ( git commit -a )</h3>
<p><code>git commit</code>에 -a 옵션을 주면 staged 상태가 아니더라도 Tracked 상태면 무조건 commit 한다.</p>
<pre><code class="language-bash">git commit -a -m &quot;force commit&quot;</code></pre>
<h3 id="파일-삭제하기--git-rm-">파일 삭제하기 ( git rm )</h3>
<p>git에서 파일을 삭제하려면 <code>git rm</code>명령어로 해당 파일을 삭제한 후 commit 해야 한다. 주의사항은 <code>git rm</code>으로 파일을 삭제하게 되면 <strong>실제 데이터도 삭제</strong> 되기 때문에 주의해야 한다.</p>
<pre><code class="language-bash">$ git rm untracked.md
rm &#39;untracked.md&#39;

$ git commit -m &quot;delete untracked.md&quot;
[master 6480c9d] delete untracked.md
 1 file changed, 1 deletion(-)
 delete mode 100644 untracked.md</code></pre>
<p>하지만 데이터를 남기고 git에서만 지울 수도 있다. <code>git rm --cached</code> 명령어를 쓰면 된다.</p>
<pre><code class="language-bash">$ git rm --cached README.md
rm &#39;README.md&#39;

$ git status
Untracked files:
  (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)
    README.md</code></pre>
<p>실제 파일은 삭제되어 지질 않았고 Untracked 상태로 바뀌었다.</p>
<h3 id="파일-이름-변경하기--git-mv-">파일 이름 변경하기 ( git mv )</h3>
<p>git에 추가 되어져 있는 파일의 이름을 바꾸고 싶을때는 <code>git mv</code>명령어를 쓰면 된다.</p>
<pre><code class="language-bash">$ git mv README.md README2.md

$ git status
On branch master
Changes to be committed:
  (use &quot;git restore --staged &lt;file&gt;...&quot; to unstage)
    renamed:    README.md -&gt; README2.md</code></pre>
<h3 id="commit-history-조회-하기--git-log-">commit history 조회 하기 ( git log )</h3>
<p><code>git log</code>를 쓰면 commit history를 조회할 수 있다. </p>
<pre><code class="language-bash">$ git log
commit 4fd6359d1c372c969d7f528a421e94a9367e2f65
Author: jeonghoon-tube &lt;shu7081@gmail.com&gt;
Date:   Tue Apr 27 22:12:48 2021 +0900

    v2

commit 761994540c0fd3c831765863c2a77e2b8f57810b
Author: jeonghoon-tube &lt;shu7081@gmail.com&gt;
Date:   Tue Apr 27 22:11:12 2021 +0900

    first commit
(END)</code></pre>
<p><code>git log</code> 의 대표적인 옵션으로는 -p 옵션과 --stat 옵션이 있다.
-p는 각 커밋의 diff 결과를 보여준다.</p>
<pre><code class="language-bash">$ git log -p -1
commit 9fdea4651f2f7e315ba06fd728bc00222fc61fd3 (HEAD -&gt; master)
Author: jeonghoon-tube &lt;shu7081@gmail.com&gt;
Date:   Tue Apr 27 22:37:35 2021 +0900

    v3

diff --git a/README.md b/README2.md
similarity index 100%
rename from README.md
rename to README2.md
(END)</code></pre>
<p>-1 옵션은 최근 한개의 결과만 보여준다.</p>
<p><code>--pretty</code> 옵션도 있다.</p>
<pre><code class="language-bash">$ git log --pretty=oneline
9fdea4651f2f7e315ba06fd728bc00222fc61fd3 (HEAD -&gt; master) v3
6480c9dacd0b78704e82366818d33dea8a508af5 delete untracked.md
4fd6359d1c372c969d7f528a421e94a9367e2f65 v2
761994540c0fd3c831765863c2a77e2b8f57810b first commit
(END)</code></pre>
<p><code>--pretty</code>옵션과 자주 쓰는 format 형식의 옵션도 있다.</p>
<pre><code class="language-bash">$ git log --pretty=format:&quot;%h - %an, %ar : %s&quot;
9fdea46 - jeonghoon-tube, 9 minutes ago : v3
6480c9d - jeonghoon-tube, 32 minutes ago : delete untracked.md
4fd6359 - jeonghoon-tube, 34 minutes ago : v2
7619945 - jeonghoon-tube, 36 minutes ago : first commit
(END)</code></pre>
<p>옵션은 밑에 서술하겠다.</p>
<table>
<thead>
<tr>
<th align="left">옵션</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left">%H</td>
<td align="left">커밋 해시</td>
</tr>
<tr>
<td align="left">%h</td>
<td align="left">짧은 커밋 해시</td>
</tr>
<tr>
<td align="left">%T</td>
<td align="left">트리 해시</td>
</tr>
<tr>
<td align="left">%t</td>
<td align="left">짧은 트리 해시</td>
</tr>
<tr>
<td align="left">%P</td>
<td align="left">부모 해시</td>
</tr>
<tr>
<td align="left">%p</td>
<td align="left">짧은 부모 해시</td>
</tr>
<tr>
<td align="left">%an</td>
<td align="left">저자 이름</td>
</tr>
<tr>
<td align="left">%ae</td>
<td align="left">저자 메일</td>
</tr>
<tr>
<td align="left">%ad</td>
<td align="left">저자 시각</td>
</tr>
<tr>
<td align="left">%ar</td>
<td align="left">저자 상대적 시각</td>
</tr>
<tr>
<td align="left">%cn</td>
<td align="left">커미터 이름</td>
</tr>
<tr>
<td align="left">%ce</td>
<td align="left">커미터 메일</td>
</tr>
<tr>
<td align="left">%cd</td>
<td align="left">커미터 시각</td>
</tr>
<tr>
<td align="left">%cr</td>
<td align="left">커미터 상대적 시각</td>
</tr>
<tr>
<td align="left">%s</td>
<td align="left">요약</td>
</tr>
</tbody></table>
<h2 id="로컬-저장소-되돌리기">로컬 저장소 되돌리기</h2>
<p>git을 되돌릴 때는 크게 두 가지 방법이 있다. <code>reset</code> 명령어와 <code>revert</code> 명령어이다.
큰 차이점은 현재 버전을 커밋으로 남기는지 안 남기는지의 차이가 있다.</p>
<h3 id="현재-커밋을-지운-후-돌아가기--git-reset-">현재 커밋을 지운 후 돌아가기 ( git reset )</h3>
<p><code>reset</code>명령어는 현재의 커밋을 남기지 않으면서 이전으로 돌아간다.
예를 들어 로컬저장소에 v1 -&gt; v2 -&gt; v3 이 커밋되어있다. <code>git reset</code>명령어를 쓰면 v1 -&gt; v2 가 된다.</p>
<h4 id="이전-내용으로-강제로-되돌리기--git-reset---hard-">이전 내용으로 강제로 되돌리기 ( git reset --hard )</h4>
<p>현재 커밋과 상관없이 강제로 이전 커밋으로 전체를 덮어 써버린다.</p>
<pre><code class="language-bash">$ cat README.md
Hi, my name is version 3

$ git log --oneline
5ee40c3 (HEAD -&gt; master) v3.0
d822cc7 v2.0
68c508b v1.0

$ git reset --hard d822cc7

$ git log --oneline
d822cc7 (HEAD -&gt; master) v2.0
68c508b v1.0

$ cat README.md
Hi, my name is version 2</code></pre>
<h4 id="현재의-작성중인-내용은-살리면서-이전-커밋으로-돌아가기--git-reset---soft-">현재의 작성중인 내용은 살리면서 이전 커밋으로 돌아가기 ( git reset --soft )</h4>
<p>현재 커밋된 버전의 내용을 둔 채 커밋만 돌아간다.</p>
<pre><code class="language-bash">$ cat README.md
Hi, my name is version 3

$ git log --oneline
5ee40c3 (HEAD -&gt; master) v3.0
d822cc7 v2.0
68c508b v1.0

$ git reset --soft d822cc7

$ git log --oneline
d822cc7 (HEAD -&gt; master) v2.0
68c508b v1.0

$ cat README.md
Hi, my name is version 3 // 커밋은 돌아갔지만 v3의 내용은 남아있다.</code></pre>
<h3 id="현재-커밋을-버전으로-남긴-후-돌아가기--git-revert-">현재 커밋을 버전으로 남긴 후 돌아가기 ( git revert )</h3>
<p><code>revert</code>명령어는 현재의 커밋을 버전으로 남긴 후 새로운 커밋을 만들면서 돌아간다.
예를 들어 로컬저장소에 v1 -&gt; v2 -&gt; v3 이 커밋되어있다. <code>git revert</code>명령어를 쓰면 v1 -&gt; v2 -&gt; v3 -&gt; v2 가 된다.
<strong>주의 해야 될 사항은 <code>git reset</code> 과는 다르게 돌아 가고싶은 커밋 번호를 적는게 아니라 취소하고 싶은 커밋을 적어줘야 한다.</strong></p>
<pre><code class="language-bash">$ git log
5ee40c3 (HEAD -&gt; master) v3.0
d822cc7 v2.0
68c508b v1.0

$ git revert 5ee40c3

$ git log --oneline
5c6a014 (HEAD -&gt; master) Revert &quot;v3.0&quot;
449c948 v3.0
b34e0c0 v2.0
7c4556d v1.0</code></pre>
<h3 id="파일-상태를-untracked로-변경하기--git-restore---staged-">파일 상태를 Untracked로 변경하기 ( git restore --staged )</h3>
<p>2개의 파일이 있는데 모르고 <code>git add .</code>명령어로 모두 staged 영역에 넣어버렸다.
둘 중에 하나를 빼야 할 때 어떻게 해야 하는가?</p>
<pre><code class="language-bash">$ git add .
$ git status
On branch master
Changes to be committed:
  (use &quot;git restore --staged &lt;file&gt;...&quot; to unstage)
    new file:   text1.md
    new file:   text2.md</code></pre>
<p>&quot;(use &quot;git restore --staged <file>...&quot; to unstage)&quot; 해당 메시지가 확인된다.
unstaged 영역으로 보내려면 해당 명령어를 입력하라는 뜻이다.</p>
<pre><code class="language-bash">$ git restore --staged text2.md
$ git status
On branch master
Changes to be committed:
  (use &quot;git restore --staged &lt;file&gt;...&quot; to unstage)
    new file:   text1.md

Untracked files:
  (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)
    text2.md</code></pre>
<p><strong>git 2.23 이전 버전에서는 `git reset HEAD &lt;파일 이름&gt;으로 뺏어야 됐다. 하지만 2.23 이후 버전에서 restore --staged &lt;파일 이름&gt;으로 바뀌였다.</strong></p>
<h2 id="원격-저장소-사용하기">원격 저장소 사용하기</h2>
<p>다른 사람들과 함께 일을 하면서 데이터를 원격저장소에 push하고 pull할수 있다.</p>
<h3 id="리모트-저장소-확인하기">리모트 저장소 확인하기</h3>
<p><code>git remote</code>명령어로 현재 프로젝트에 등록된 리모트 저장소를 확인할 수 있다.
저장소를 clone 하면 origin이라는 리모트 저장소가 자동으로 등록되기 때문에 origin이라는 이름을 볼 수 있다.</p>
<pre><code class="language-bash">$ git clone https://github.com/tube-jeonghoon/tube-jeonghoon.git
$ cd tube-jeonghoon
$ git remote
origin</code></pre>
<h3 id="리모트-저장소-추가하기--git-remote-add-">리모트 저장소 추가하기 ( git remote add )</h3>
<p>새 리모트 저장소는 쉽게 추가할 수 있다. <code>git remote add [단축 이름] [URL]</code>명령어를 쓰면 된다.</p>
<pre><code class="language-bash">$ git remote add tube https://github.com/tube-jeonghoon/git-test.git
$ git remote -v
tube    https://github.com/tube-jeonghoon/git-test.git (fetch)
tube    https://github.com/tube-jeonghoon/git-test.git (push)</code></pre>
<p>이제 원격 저장소에서 로컬 저장소로 데이터를 가져올 때 URL 대신에 단축 이름을 사용할 수 있다.</p>
<pre><code class="language-bash">$ git pull tube
Updating bd1e8dd..347ec38
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)</code></pre>
<h3 id="원격-저장소에-있는-데이터-가져오기--git-pull-git-fetch-">원격 저장소에 있는 데이터 가져오기 ( git pull, git fetch )</h3>
<p><code>git pull</code>과 <code>git fetch</code>에는 차이점이 있다. <code>git fetch</code>는 원격 저장소에 있는 모든 데이터를 로컬로 가져오지만 자동으로 병합(merge) 하지는 않는다. 로컬에서 하는 작업을 모두 마무리하고 수동으로 병합(merge) 해 줘야 한다. 하지만 <code>git pull</code>은 로컬로 데이터를 가져오면서 자동으로 병합(merge) 한다.</p>
<pre><code class="language-bash">$ git pull tube
Updating bd1e8dd..347ec38
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)</code></pre>
<h3 id="원격-저장소에-push하기--git-push-">원격 저장소에 push하기 ( git push )</h3>
<p>프로젝트를 원격 저장소에 올리고 싶을 때 <code>git push</code> 명령어를 사용할 수 있다. 사용 방법은 <strong>git push [원격 저장소 이름] [브랜치 이름]</strong>으로 사용하면 된다.</p>
<pre><code class="language-bash">$ git push tube master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 288 bytes | 288.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/tube-jeonghoon/git-test.git
   347ec38..74ddcfe  master -&gt; master</code></pre>
<p>주의 사항으로는 이 방법은 다른 사람이 push 한 뒤에는 push 할 수 없고 원격 저장소에 있는 내용을 가져와(pull) 병합(merge) 한 다음 push 할 수 있다. 자세한 방법은 후술하도록 하겠다.</p>
<h3 id="원격-저장소-살펴보기--git-remote-show-">원격 저장소 살펴보기 ( git remote show )</h3>
<p><code>git remote show [저장소 이름]</code>으로 해당 저장소의 구체적인 정보를 확인할 수 있다.</p>
<pre><code class="language-bash">$ git remote show tube
* remote tube
  Fetch URL: https://github.com/tube-jeonghoon/git-test.git
  Push  URL: https://github.com/tube-jeonghoon/git-test.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for &#39;git pull&#39;:
    master merges with remote master
  Local ref configured for &#39;git push&#39;:
    master pushes to master (up to date)</code></pre>
<h3 id="원격-저장소-수정-및-삭제--git-remote-rename-">원격 저장소 수정 및 삭제 ( git remote rename )</h3>
<p><code>git remote rename</code>명령어를 사용하면 저장소의 이름을 변경할 수 있다.</p>
<pre><code class="language-bash">$ git remote rename tube wow-tube
$ git remote
origin
wow-tube</code></pre>
<p><code>git remote rm</code> 명령어로 저장소를 삭제할 수도 있다.</p>
<pre><code class="language-bash">$ git remote rm origin
$ git remote
wow-tube</code></pre>
<h3 id="태그-사용하기--git-tag-">태그 사용하기 ( git tag )</h3>
<p>Git에는 tag를 지원한다. 보통 릴리스할 때 사용한다.</p>
<h4 id="태그-조회하기--git-tag-">태그 조회하기 ( git tag )</h4>
<p><code>git tag</code>명령어로 현재 있는 태그를 확인 할 수 있다</p>
<pre><code class="language-bash">$ git tag</code></pre>
<h4 id="태그-붙이기">태그 붙이기</h4>
<p>Git 태그에는 Annotated 태그와 Lightweight 태그 두 가지 종류가 있다.</p>
<h5 id="lightweight-태그">Lightweight 태그</h5>
<p>브랜치처럼 가리키는 지점을 최신커밋으로 이동시키지 않는다. 단순히 특정 커밋에 대한 포인터 역활만 한다.</p>
<pre><code class="language-bash">$ git tag v1.4-tube
$ git show v1.4-tube</code></pre>
<h5 id="annotated-태그">Annotated 태그</h5>
<p>Git 데이터베이스에 태그를 만든 사람의 이름, 이메일과 태그를 만든 날짜, 태그 메시지도 저장하며 -a 옵션과 -m 옵션이 있다. Annotated 태그를 추가할 때 -a를 붙이고 -m으로 태그 메시지도 함께 저장할 수 있다.</p>
<pre><code class="language-bash">$ git tag -a v1.4-tube -m &quot;my version 1.4&quot;
$ git show v1.4</code></pre>
<h4 id="나중에-태그-하기">나중에 태그 하기</h4>
<p>이전 커밋에 태그를 붙일 때가 발생할 수도 있다. <strong>git tag -a [태그 이름] [커밋 체크 섬]</strong>으로 추가할 수 있다. 커밋 체크 섬 값은 길어서 전부 쓸 수 없다면 일부만 적어줘도 된다.</p>
<pre><code class="language-bash">$ git log --pretty=oneline
74ddcfee4306cdfe416764814597a8a0161f1eab (HEAD -&gt; master, tag: v1.4-tube, tag: v1.4, wow-tube/master) add testfile.md
347ec386a0deb178c8f4af00def1ec7c3a93f30c Update README.md
bd1e8dd285d7f1f0ba3d7948888b8dcf8a682c16 first commit

$ git tag -a v1.3 -m &quot;my version 1.3&quot; 347e
$ git log --pretty=oneline
74ddcfee4306cdfe416764814597a8a0161f1eab (HEAD -&gt; master, tag: v1.4-tube, tag: v1.4, wow-tube/master) add testfile.md
347ec386a0deb178c8f4af00def1ec7c3a93f30c (tag: v1.3) Update README.md
bd1e8dd285d7f1f0ba3d7948888b8dcf8a682c16 first commit</code></pre>
<p>Update README.md 커밋에 tag가 성공적으로 붙었다.</p>
<h3 id="git-단축어-설정--git-alias-">git 단축어 설정 ( git alias )</h3>
<p>명령어를 alias에 등록해 간단하게 쓸 수 있다. <code>git config --global</code>명령어를 쓰면 된다. 해당 프로젝트에서만 쓰고 싶음면 <code>--global</code> 옵션은 빼도 무방하다.</p>
<pre><code class="language-bash">$ git config alias.st status
$ git st
On branch master
Your branch is up to date with &#39;wow-tube/master&#39;.

nothing to commit, working tree clean</code></pre>
<p>몇 가지 자주 등록해 두면 편한 단축키이다.</p>
<pre><code class="language-bash">$ git config alias.last &#39;log -1 HEAD&#39; // 마지막 커밋 출력
$ git config alias.untracked &#39;restore --staged&#39;
$ git config --global alias.logl &#39;log --oneline --decorate --graph --all&#39;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ubuntu에 anaconda 설치하기]]></title>
            <link>https://velog.io/@tube-jeonghoon/Ubuntu%EC%97%90-anaconda-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@tube-jeonghoon/Ubuntu%EC%97%90-anaconda-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 25 Apr 2021 12:06:42 GMT</pubDate>
            <description><![CDATA[<h2 id="anaconda-다운로드-전-의존성-라이브러리-설치">anaconda 다운로드 전 의존성 라이브러리 설치</h2>
<pre><code class="language-bash">$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6</code></pre>
<h2 id="anaconda-다운로드">anaconda 다운로드</h2>
<p><a href="https://www.anaconda.com/products/individual#download-section">https://www.anaconda.com/products/individual#download-section</a> 해당 사이트에서 아나콘다 버전 확인 후 다운로드</p>
<pre><code class="language-bash">$ wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh</code></pre>
<h2 id="anaconda-설치">anaconda 설치</h2>
<pre><code class="language-bash">$ zsh Anaconda3-2020.11-Linux-x86_64.sh</code></pre>
<h2 id="환경변수-설정">환경변수 설정</h2>
<h3 id="쉘-확인">쉘 확인</h3>
<pre><code class="language-bash">$ echo $SHELL
/usr/bin/zsh</code></pre>
<h3 id="환경변수-추가">환경변수 추가</h3>
<p><code>~/.zshrc</code> 및 <code>~/.bashrc</code>파일에 해당 내용추가</p>
<pre><code class="language-bash">export PATH=$HOME/anaconda3/bin:$PATH</code></pre>
<h3 id="환경변수-적용">환경변수 적용</h3>
<pre><code class="language-bash">$ source ~/.zshrc
$ source ~/.bashrc</code></pre>
<h3 id="conda-init">conda init</h3>
<pre><code class="language-bash">$ conda init zsh</code></pre>
<p>현재 실행 중인 터미널을 재실행 시켜야 한다.</p>
<h2 id="설치-완료-확인">설치 완료 확인</h2>
<pre><code class="language-bash">$ conda --version
conda 4.9.2</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[마크다운 문법 익히기]]></title>
            <link>https://velog.io/@tube-jeonghoon/%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4-%EB%AC%B8%EB%B2%95-%EC%9D%B5%ED%9E%88%EA%B8%B0</link>
            <guid>https://velog.io/@tube-jeonghoon/%EB%A7%88%ED%81%AC%EB%8B%A4%EC%9A%B4-%EB%AC%B8%EB%B2%95-%EC%9D%B5%ED%9E%88%EA%B8%B0</guid>
            <pubDate>Wed, 21 Apr 2021 09:50:53 GMT</pubDate>
            <description><![CDATA[<h2 id="시작">시작</h2>
<p>앞으로 <code>velog</code>에 기술문서를 작성할 예정이다.
일단 마크다운 문법부터 익혀야 되는데 일단은 문서로 작성해 두고 써야겟다.</p>
<blockquote>
<p>마크다운 (Markdown)은 마크업 언어의 일종으로, 존 그루버(John Gruber)와 아론 스워츠(Aaron Swartz)가 만들었다. 마크다운 문법은 읽기도 쉽지만 쓰기도 쉽다는 장점이 있다. 확장자는 .md를 쓴다.</p>
</blockquote>
<hr>
<h3 id="제목">제목</h3>
<pre><code class="language-markdown"># 제목 1
## 제목 2
### 제목 3
#### 제목 4
##### 제목 5
###### 제목 6</code></pre>
<p>제목의 수준과 서식을 결정한다.</p>
<hr>
<h3 id="강조">강조</h3>
<pre><code class="language-markdown">__내용__
_내용_
~~내용~~</code></pre>
<p><strong>내용</strong></p>
<p><em>내용</em></p>
<p><del>내용</del></p>
<hr>
<h3 id="목록">목록</h3>
<pre><code class="language-markdown">1. 순서가
- 순서가
2. 필요한
* 필요하지
3. 목록
+ 않은 목록</code></pre>
<ol>
<li>순서가</li>
</ol>
<ul>
<li>순서가</li>
</ul>
<ol start="2">
<li>필요한</li>
</ol>
<ul>
<li>필요하지</li>
</ul>
<ol start="3">
<li>목록</li>
</ol>
<ul>
<li>않은 목록</li>
</ul>
<hr>
<h3 id="링크">링크</h3>
<pre><code class="language-markdown">[google](https://google.com)
[python](https://www.python.org &quot;파이썬 홈페이지 입니다.&quot;)
[facebook][facebook link]
[youtube][1]

내용 

[facebook link]: https://www.facebook.com
[1]: https://youtube.com</code></pre>
<p><a href="https://google.com">google</a></p>
<p><a href="https://www.python.org" title="파이썬 홈페이지 입니다.">python</a></p>
<p><a href="https://www.facebook.com">facebook</a></p>
<p><a href="https://youtube.com">youtube</a></p>
<p>내용 </p>
<hr>
<h3 id="이미지">이미지</h3>
<pre><code class="language-markdown">![대체텍스트](https://media.routard.com/image/67/1/fb-canada-parcs.1473671.jpg)</code></pre>
<p><img src="https://media.routard.com/image/67/1/fb-canada-parcs.1473671.jpg" alt="대체텍스트"></p>
<hr>
<h3 id="코드">코드</h3>
<pre><code class="language-markdown">`markdown`은 정말 쉽습니다.</code></pre>
<p><code>markdown</code>은 정말 쉽습니다.</p>
<hr>
<h3 id="코드블럭">코드블럭</h3>
<pre><code class="language-javascript">var userId = 1
var userName = &#39;Tube&#39;

var user = { id:1, name:&#39;Tube&#39; }
var users = [
    { id:1, name:&#39;Tube&#39; },
    { id:2, name:&#39;jeonghoon&#39; }
]</code></pre>
<pre><code class="language-bash">$ cat /etc/passwd</code></pre>
<hr>
<h3 id="표">표</h3>
<pre><code class="language-markdown">| value | name | color |
|---|:---:|---:|
| 1 | TUBE | `Brown` |
| 2 | MUZI | White |
| 3 | APEACH | Pink |
| 4 | FRODO | Brown |</code></pre>
<table>
<thead>
<tr>
<th align="right">value</th>
<th align="center">name</th>
<th align="center">color</th>
</tr>
</thead>
<tbody><tr>
<td align="right">1</td>
<td align="center">TUBE</td>
<td align="center"><code>Brown</code></td>
</tr>
<tr>
<td align="right">2</td>
<td align="center">MUZI</td>
<td align="center">White</td>
</tr>
<tr>
<td align="right">3</td>
<td align="center">APEACH</td>
<td align="center">Pink</td>
</tr>
<tr>
<td align="right">4</td>
<td align="center">FRODO</td>
<td align="center">Brown</td>
</tr>
</tbody></table>
<hr>
<h3 id="인용">인용</h3>
<pre><code class="language-markdown">&gt; 이것은 인용문 입니다.
&gt;&gt; 이렇게 중첩해서 사용할수도 있어요.</code></pre>
<blockquote>
<p>이것은 인용문 입니다.</p>
<blockquote>
<p>이렇게 중첩해서 사용할수도 있어요.</p>
</blockquote>
</blockquote>
<hr>
<h3 id="수평선">수평선</h3>
<pre><code class="language-markdown">---
***
___</code></pre>
<hr>
<hr>
<hr>
]]></description>
        </item>
    </channel>
</rss>