728x90
반응형

해당 에러는 vscode의 typescript와 로컬 typescript의 버전이 맞지 않아서 생긴다.

 

1. vscode의 settings.json 파일에 다음을 추가해준다.

작업 영역의 루트 폴더에서 해야한다. 경로 안의 프로젝트에 typescript를 설치했다면 경로를 인식하지 못한다.

또한 로컬 내에 타입스크립트의 버전과 vscode 타입스크립트의 버전을 꼭 확인해야한다.

{
	"typescript.tsdk": "node_modules/typescript/lib"
}

그 다음 vscode를 껐다 키고 f1을 누르면

이렇게 나오는데, 두 번째 작업 영역 버전을 사용하면 된다.

728x90
반응형
728x90
반응형

기존 js로 되어있던 프로젝트를 typescript로 변경해야 될 때가 있다.

 

1. 필요한 패키지 다운로드

$ npm i typescript ts-loader @types/node @types/react @types/react-dom @types/jest --dev

2. tsc 명령어 안먹힘

window로 작업하던 중 tsc 명령어가 안 먹히는 것을 보고 해결법을 찾았다. 아래와 같은 오류일 때 가능하다.

tsc : 'tsc' 용어가 cmdlet, 함수, 스크립트 파일 또는 실행할 수 있는 프로그램 이름으로 인식되지 않습니다. 
 이름이 정확한지 확인하고 경로가 포함된 경우 경로가 올바른지 검증한 다음 다시 시도하십시오.

 

window 파워 셀을 관리자 권한으로 실행한 뒤 권한을 RemoteSigned로 바꿔준다.

 

3. tsconfig.json 파일 생성

tsc --init 명령어로 tsconfig.json 파일을 만든 뒤에 다음과 같이 작성한다. 옵션을 꼭 따라할 필요는 없다.

{
  "compileOnSave": true,
  "compilerOptions": {
    "target": "es2016",
    "jsx": "react-jsx",
    "module": "esnext",
    "sourceMap": true,
    "removeComments": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "noFallthroughCasesInSwitch": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": false
  },
  "include": [
    "./src/*"
  ],
  "exclude": [
    "node_modules/*"
  ]
}

 

4. webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

기존 webpack 파일에 필요한 부분을 채워넣어준다.

 

혹시 기존에 babel 을 사용하고 있었다면 .babelrc 파일에 아래를 추가하고

"preset" : ["@babel/preset-typescript"]

webpack 파일에 다음을 추가해주자.

      {
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },

 

4. 컴파일

$ tsc

 

혹시 컴파일 시 결과를 터미널에서 알고 싶을 때는 tsconfig.json 폴더에서 noemit 부분을 false로 바꿔준다.

컴파일 하고 Cannot write file '경로' because it would overwrite input file.

이런 에러가 뜬다면

{
  "compilerOptions": {
    "outDir": "build",
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build/**/*"]
}

outDir 폴더를 만들어주고, exclude 시켜준다.

 

tsc 명령어로 에러가 안뜬다면 webpack을 실행해준다.

$ npx webpack

 

참고로 tsc 다음에 파일 명을 쓴다면 tsconfig.json이 안먹힌다!

5. can only be default-imported using the 'esModuleInterop' flag

위와 같은 에러가 뜬다면 tsconfig.json 파일에 "esModuleInterop": true, 속성을 추가해주자.

기존 CommonJS 모듈을 ES6모듈 사양을 준수하여 가져올 수 있게 된다.

728x90
반응형
728x90
반응형

레거시 코드를 빌드하는데 에러가 떠버렸다.

누가 짰는진 모르겠지만 이 코드는 답이 없었다...

 

일단 오늘 빌드를 무조건 해야하는 상황이라 확실한 방법은 나중에 찾아봐야겠다.

다음 주부터 처음부터 다시 만들어야겠다.

module.exports = {
    webpack: (config, { isServer }) => {
        if (!isServer) {
             config.resolve.fallback.fs = false
             config.resolve.fallback.dns = false
             config.resolve.fallback.net = false
        }

        return config;
    }
}
728x90
반응형
728x90
반응형

개요

React 로 개발을 하면서 프론트 서버가 가끔 강제 종료되는 일이 자주 발생했다.
JavaScript heap out of memory 라고 오류 메세지가 출력 되는데
이유를 살펴보니 node.js가 과도하게 메모리 점유를 해서 발생한다.
해결 방법으로 더 큰 메모리를 할당 해 주면 된다고 하여 8GB를 할당 해 주었다.

해결 1

할당 해주는 방법은
터미널에

export NODE_OPTIONS="--max-old-space-size=8192"

위 코드를 입력해주면 해결 된다.

하지만 대부분 1시간을 버티지 못하도 다시 서버가 강제 종료 되었다.

알고 보니 너무 많이 할당을 해주어도 문제이다.

내 노트북은 8gb 램인데 다 할당을 해주니 다른 프로그램이 할당 받을 것을 다 뺏어버린 것이다.
결국 충돌로 꺼지게 된다는것을 알게 되었다.
과유 불급이었다.

해결 2

그래서 1gb부터 8gb까지 1기가씩 증가시켜서 램을 할당 해주니 3gb가 딱 적당했다.
export NODE_OPTIONS="--max-old-space-size=3072"

나는 이 오류로 2달을 고생했다. 지금이라도 고쳐서 다행이다.
구글링으로 알기 어려우니 글을 남겨서 다른 사람들도 램을 적당히 할당해주길 바란다.

1gb ~ 8gb

1GB ~ 8GB 할당 명령어

#1gb
export NODE_OPTIONS="--max-old-space-size=1024"

#2gb
export NODE_OPTIONS="--max-old-space-size=2048"

#3gb
export NODE_OPTIONS="--max-old-space-size=3072"

#4gb
export NODE_OPTIONS="--max-old-space-size=4096"

#5gb
export NODE_OPTIONS="--max-old-space-size=5120"

#6gb
export NODE_OPTIONS="--max-old-space-size=6144"

#7gb
export NODE_OPTIONS="--max-old-space-size=7168"

#8gb 
export NODE_OPTIONS="--max-old-space-size=8192"

8gb 이상 할당은 해주지 말자.
gb계산이 귀찮으니 위 코드를 복붙해서 사용하길 바란다.

etc

CRA가 아닌 node에서 발생해도 해결이 가능하다.

 
728x90
반응형
728x90
반응형

React에서는 줄바꿈을 허용하지 않는다. 때문에 매핑하고 <br /> 태그를 임의로 주어서 줄바꿈을 표기해주자.

 

<Wrap ai={`start`} margin={`25px 0 0 0`}>
                {state.post_content.split("\n").map((line: any) => { //this.props.data.content: 내용
                  return (
                    <span>
                      {line}
                      <br />
                    </span>
                  );
                })}
              </Wrap>

 

728x90
반응형
728x90
반응형
// 스크롤이 50px 이상 내려올경우 true값을 넣어줄 useState
const [scroll, setScroll] = useState(false);

useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll); //clean up
    };
  }, []);

const handleScroll = () => {
	console.log("window.scrollY : ", window.scrollY)
  };

 

기준점을 잡고 현재 상태에서 올라갔는지 내려갔는지를 보려면 state가 아닌 일반 변수를 써야한다.

var scroll = 0;
    useEffect(() => {
        window.addEventListener('scroll', () => {
            // 검색등을 한 뒤 스크롤이 맨 위일 때는 임의로 컴포넌트를 보여주게 함.
            if (window.scrollY === 0) {
                dispatch({ name: "scrollUp", value: true })
            }
            // 스크롤이 맨 마지막에 도달했을 때
            else {
                if (Math.round(document.documentElement.scrollTop + window.innerHeight) - document.body.scrollHeight > -10) {
                    dispatch({ name: "scrollUp", value: false });
                }
                else if ((window.scrollY) < 10) {
                    dispatch({ name: "scrollUp", value: true });
                }
                else {
                    if (scroll < window.scrollY) {
                        dispatch({ name: "scrollUp", value: false });
                    }
                    else {
                        dispatch({ name: "scrollUp", value: true });
                    }
                }
            }

            scroll = window.scrollY;
        });
    }, []);
728x90
반응형
728x90
반응형
const beforeMinute = (date: any) => {
    const today = new Date();
    const timeValue = new Date(date);

    const betweenTime = Math.floor((today.getTime() - timeValue.getTime()) / 1000 / 60);
    if (betweenTime < 1) return '방금전';
    if (betweenTime < 60) {
        return `${betweenTime}분전`;
    }

    const betweenTimeHour = Math.floor(betweenTime / 60);
    if (betweenTimeHour < 24) {
        return `${betweenTimeHour}시간전`;
    }

    const betweenTimeDay = Math.floor(betweenTime / 60 / 24);
    if (betweenTimeDay < 365) {
        return `${betweenTimeDay}일전`;
    }

    return date;
}

 

const stringEllipsis = (str: string) => {
    let length = 30; // 표시할 글자수 기준
    if (str.length > length) {
        str = str.substring(0, length - 2) + '...';
    }
    return str;
}
728x90
반응형
728x90
반응형

1. 네이버 디벨로퍼 로그인

https://developers.naver.com/main/

 

NAVER Developers

네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음

developers.naver.com

 

2. 애플리케이션 등록

 

3. 환경 추가

개발 환경에서 실행해볼 것이기 때문에 일단은 localhost로 설정해둔다.

다 하고 애플리케이션을 확인하면 아래와 같은 화면을 볼 수 있다.

 

4._app.tsx 파일에  script 추가

const MyApp: NextPage<AppProps> = ({ Component, pageProps }: AppProps) => {


  return (
    <React.StrictMode>
      <Head>
        <title></title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />

        <script src="https://developers.kakao.com/sdk/js/kakao.js"
          defer
        >
        </script>
        
        <script src="https://static.nid.naver.com/js/naveridlogin_js_sdk_2.0.2.js"></script>


      </Head >
      <ThemeProvider theme={Theme}>
          <Component {...pageProps} />
      </ThemeProvider>


    </React.StrictMode>
  );
};

 

5. Component 구현 ( 전체 코드 )

import { GetServerSideProps, NextPage } from "next";
import { useRouter } from "next/router";
import { useEffect, useReducer, useState } from "react";

const Community: NextPage<any> = (props: any) => {
    const router = useRouter();

    const stateInit = {
        email: ""
    };

    const [state, dispatch] = useReducer(reducer, stateInit);

    function reducer(state: any, action: any) {
        switch (action.type) {
            case "init":
                return stateInit;
            default:
                return {
                    ...state,
                    [action.name]: action.value
                }
        }
    }



    useEffect(() => {
        const naver = (window as any).naver;
        let naverLogin: any;

        const login = () => {
            naverLogin = new naver.LoginWithNaverId({
                clientId: 'ClientID', // ClientID
                callbackUrl: 'Callback URL', // Callback URL
                isPopup: false, // 팝업 형태로 인증 여부
                loginButton: {
                    color: 'green', // 색상
                    type: 3, // 버튼 크기
                    height: '60' // 버튼 높이
                }, // 로그인 버튼 설정
            })

            naverLogin.init();
        }

        const getToken = () => {
            const hash = router.asPath.split('#')[1]; // 네이버 로그인을 통해 전달받은 hash 값
            if (hash) {
                const token = hash.split('=')[1].split('&')[0]; // token값 확인
                naverLogin.getLoginStatus((status: any) => {
                    if (status) { // 로그인 상태 값이 있을 경우
                        console.log(naverLogin.user.email); // 사용자 정보 조회

                        // if (!naverLogin.user.getAge()) { // 나이정보 제공을 동의하지 않았을 경우
                        //     alert('나이 정보는 필수입니다.');
                        //     naverLogin.reprompt(); // 정보제공창 다시 보여주기

                        //     return;
                        // }
                        dispatch({ name: "email", value: naverLogin.user.email })
                        // /community 페이지로 token값과 함께 전달 (서비스할 땐 token 전달을 하지 않고 상태 관리를 사용하는 것이 바람직할 것으로 보임)
                        router.push({
                            pathname: '/community',
                            query: {
                                token: token,
                            }
                        })
                    }
                });
            }
        }

        login();
        getToken();
    }, [])


    const kakaoInit = () => {
        const kakao = (window as any).Kakao;
        if (!kakao.isInitialized()) {
            kakao.init(process.env.NEXT_PUBLIC_KAKAO_SHARE_KEY);
        }

        return kakao;
    }

    const kakaoLogin = async () => {
        // 카카오 초기화
        const kakao = kakaoInit();

        // 카카오 로그인 구현
        kakao.Auth.login({
            success: () => {
                kakao.API.request({
                    url: '/v2/user/me', // 사용자 정보 가져오기
                    success: (res: any) => {
                        // 로그인 성공할 경우 정보 확인 후 /kakao 페이지로 push
                        console.log(res.kakao_account);
                        if (!res.kakao_account.email || res.kakao_account.email === "") {
                            alert("해당 계정의 이메일이 존재하지 않습니다.")
                        }
                        else {
                            dispatch({ name: "email", value: res.kakao_account.email })
                        }

                        // router.push('/kakao');
                    },
                    fail: (error: any) => {
                        console.log(error);
                    }
                })
            },
            fail: (error: any) => {
                console.log(error);
            }
        })
    }

    console.log("state : ", state)

    return (
        <>
            <button onClick={(e: any) => { kakaoLogin(); }}>
                카톡으로 로그인
            </button>
            <button id={`naverIdLogin`}>
                네이버 로그인
            </button>
        </>
    )
}

export default Community;

export const getServerSideProps: GetServerSideProps = async (context) => {
    return {
        props: {

        }
    }
}

 

네이버 로그인은 카카오톡과는 다르게 로그인이 성공하면 redirect 되면서 url에 파라미터가 넘어가는 형식으로 되어있다.

이 점을 유의하자.

728x90
반응형
728x90
반응형

로그인

1. 카카오 디벨로퍼 로그인

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

2. 애플리케이션 추가

 

3. 플랫폼 도메인 설정 후 등록하러가기 버튼 클릭

4. 로그인 활성화 및 Redirect URI 설정

5. 동의 항목 설정

 

6. _app.tsx 파일에  script 추가

_app.tsx

const MyApp: NextPage<AppProps> = ({ Component, pageProps }: AppProps) => {


  return (
    <React.StrictMode>
      <Head>
        <title></title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />

        <script src="https://developers.kakao.com/sdk/js/kakao.js"
          defer
        >
        </script>


      </Head >
      <ThemeProvider theme={Theme}>
          <Component {...pageProps} />
      </ThemeProvider>


    </React.StrictMode>
  );
};

 

7. 쿠키 생성 라우터 ( Back-end )

community.js

var express = require('express');
var router = express.Router();

const jwt = require("jsonwebtoken");

router.post("/login", async function (req, res, next) {

    const body = req.body;

    const tokenValue = {
        email: body.email
    }

    const token = jwt.sign({ isLogined: tokenValue }, "secretkey", {
        expiresIn: 86400000, // 토큰 제한시간
    });

    res.cookie("A12Ba5os9", token, {
        maxAge: 86400000, // 쿠키 제한시간
        path: "/",
        httpOnly: true,
    });

    return res.send({ success: true })
})

module.exports = router;

 

8.  컴포넌트에 구현

import { GetServerSideProps, NextPage } from "next";
import { useRouter } from "next/router";

const Community: NextPage<any> = (props: any) => {
    const router = useRouter();

    const kakaoInit = () => {
        const kakao = (window as any).Kakao;
        if (!kakao.isInitialized()) {
            kakao.init(process.env.NEXT_PUBLIC_KAKAO_SHARE_KEY);
        }

        return kakao;
    }

    const kakaoLogin = async () => {
        // 카카오 초기화
        const kakao = kakaoInit();

        // 카카오 로그인 구현
        kakao.Auth.login({
            success: () => {
                kakao.API.request({
                    url: '/v2/user/me', // 사용자 정보 가져오기
                    success: (res: any) => {
                        // 로그인 성공할 경우 
                        if (!res.kakao_account.email || res.kakao_account.email === "") {
                            alert("해당 계정의 이메일이 존재하지 않습니다.")
                        }
                        else {
                        	// 쿠키 생성
                            await axios.post("/api/community/login", { email: res.kakao_account.email })
                                .then(({ data }) => {
                                    if (data.success) {
                                        dispatch({ name: "email", value: res.kakao_account.email })
                                    }
                                    else {
                                        return alert(" 로그인에 실패하였습니다.")
                                    }
                                })
                        }
                        
                    },
                    fail: (error: any) => {
                        console.log(error);
                    }
                })
            },
            fail: (error: any) => {
                console.log(error);
            }
        })
    }

    return (
        <>
            <button onClick={(e: any) => { kakaoLogin(); }}>
                카톡으로 로그인
            </button>
        </>
    )
}

export default Community;

export const getServerSideProps: GetServerSideProps = async (context) => {
    return {
        props: {

        }
    }
}

/api 로 시작하는 라우터는 next.config.js 로 백엔드 프록시 설정을 해서 그렇습니다.

9. 확인하기


로그아웃

카카오 로그아웃은 이 사이트 뿐만 아니라 카카오 소셜 계정 자체를 로그아웃 시켜야 하는데,

https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#logout-of-service-and-kakaoaccount

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

카카오에서 제공하는 api를 사용해야 한다.

 

1. Logout Redirect URI 설정

 

2. 쿠키 삭제 라우터 ( Back-end )

var express = require('express');
var router = express.Router();

const jwt = require("jsonwebtoken");

router.post("/login", async function (req, res, next) {

    const body = req.body;

    const tokenValue = {
        email: body.email
    }

    const token = jwt.sign({ isLogined: tokenValue }, "secretkey", {
        expiresIn: 86400000, // 토큰 제한시간
    });

    res.cookie("A12Ba5os9", token, {
        maxAge: 86400000, // 쿠키 제한시간
        path: "/",
        httpOnly: true,
    });

    return res.send({ success: true })
})

router.post("/logout", async function (req, res, next) {

    res.clearCookie("A12Ba5os9");

    return res.send({ success: true })
})


module.exports = router;

 

3. 컴포넌트 구현

import { GetServerSideProps, NextPage } from "next";
import { useRouter } from "next/router";

const Community: NextPage<any> = (props: any) => {
    const router = useRouter();

    const kakaoInit = () => {
        const kakao = (window as any).Kakao;
        if (!kakao.isInitialized()) {
            kakao.init(process.env.NEXT_PUBLIC_KAKAO_SHARE_KEY);
        }

        return kakao;
    }

    const kakaoLogin = async () => {
        // 카카오 초기화
        const kakao = kakaoInit();

        // 카카오 로그인 구현
        kakao.Auth.login({
            success: () => {
                kakao.API.request({
                    url: '/v2/user/me', // 사용자 정보 가져오기
                    success: (res: any) => {
                        // 로그인 성공할 경우 
                        if (!res.kakao_account.email || res.kakao_account.email === "") {
                            alert("해당 계정의 이메일이 존재하지 않습니다.")
                        }
                        else {
                        	// 쿠키 생성
                            await axios.post("/api/community/login", { email: res.kakao_account.email })
                                .then(({ data }) => {
                                    if (data.success) {
                                        dispatch({ name: "email", value: res.kakao_account.email })
                                    }
                                    else {
                                        return alert(" 로그인에 실패하였습니다.")
                                    }
                                })
                        }
                    },
                    fail: (error: any) => {
                        console.log(error);
                    }
                })
            },
            fail: (error: any) => {
                console.log(error);
            }
        })
    }
    
    const kakaoLogout = async () => {
        // 쿠키 제거
        await axios.post("/api/community/logout", state)
            .then(({ data }) => {
                if (data.success) {
                    dispatch({ type: "init" })
                    // 카카오 로그아웃 페이지
                    router.push(`https://kauth.kakao.com/oauth/logout?client_id=${process.env.NEXT_PUBLIC_KAKAO_SHARE_KEY}&logout_redirect_uri=http://localhost:3001`);
                }
                else {
                    return alert(" 로그아웃에 실패하였습니다.")
                }
            })
    }

    return (
        <>
            <button onClick={(e: any) => { kakaoLogin(); }}>
                카톡으로 로그인
            </button>
            <button onClick={(e: any) => { kakaoLogout(); }}>
                로그아웃
            </button>
        </>
    )
}

export default Community;

export const getServerSideProps: GetServerSideProps = async (context) => {
    return {
        props: {

        }
    }
}

로그인을 했을 경우 SSR로 props를 넘기면 쿠키 데이터를 읽어 로그인 된 상태를 구현할 수 있다. 

( 로그인 or 로그아웃 버튼 보이게끔 하는거 구현 가능 )

4. 로그아웃 

  • 이 서비스만 로그아웃 : state 가 초기화 되었고, 쿠키가 삭제되었으므로 사이트는 로그아웃 됨. ( 하지만 로그인할 때 전에 했던 방식으로 로그인 됨 )
  • 카카오계정과 함께 로그아웃 : 소셜 계정이 로그아웃 되어 다른 계정으로 로그인 가능

 

728x90
반응형
728x90
반응형

1. reset

아직 원격 저장소에 push하기 전이라면 reset을 사용할 수 있다.

없애고 싶은 커밋이 있을 때, reset을 이용하면 해당 커밋을 흔적도 없이 지울 수 있다.

 

문법은 아래와 같다.

$ git reset --옵션 커밋해시

옵션으로는 hard, soft, mixed 등이 있고,

커밋해시에는 돌아가고 싶은 커밋의 해시 주소를 입력하면 된다.

 

옵션에 대해 간략하게 살펴보자.

 

1) hard

돌아가려는 커밋 이후의 모든 내용을 지워 버린다.

staging area와 working directory 모두 돌아가려는 커밋과 동일해진다.

 

2) soft

돌아가려는 커밋으로 되돌아가고, HEAD가 돌아가려는 커밋을 새롭게 가리키게 된다.

staging area와 working directory는 아무런 변화도 없다.

 

3) mixed

돌아가려는 커밋으로 되돌아가고, HEAD가 돌아가려는 커밋을 새롭게 가리키게 된다.

staging area는 돌아가려는 커밋과 동일해지고, working directory는 아무 변화가 없다.

 

그다음 git push를 해준다.

$ git push --force --set-upstream origin master

git log를 다시 찍어보면 revert가 잘 된 것을 확인할 수 있을 것이다.

 

 

2. revert

이미 원격 저장소에 push한 상태라면 reset은 사용할 수 없고 revert를 사용해야 한다.

이것이 reset과 revert의 차이이다.

 

그렇다면 revert의 사용방법에 대해 알아보자.

 

우선 git log로 해시주소를 파악해야 한다.

git log 찍고, 커밋이 다음의 commit1>2>3의 순서로 발생했다고 해보자.

오른쪽에 뜨는 것이 git hash이다.

commit3        54c6547
commit2        a516d21
commit1        4567289    // 되돌아가려는 커밋

 

내가 돌아가려는 커밋이 commit1이면,

commit3를 먼저 revert하고 이후 commit2를 revert하는 방식으로 순차적으로 진행해야 한다.

아래와 같이 입력하면 된다.

$ git revert 54c6547
$ git revert a516d21

 

그다음 git push를 해준다.

$ git push --force --set-upstream origin master

 

git log를 다시 찍어보면 revert가 잘 된 것을 확인할 수 있을 것이다.

728x90
반응형

+ Recent posts