Git GUI에서 패치 일부를 제출하는 일본어 기능 지원

10661 단어 GitWindowsmsysGit

패치 제출 기능


Git 는 git add -p 에서 변경 사항의 일부만 단계 → 커밋하는 기능을 가지고 있습니다.
그리고 Git GUI를 사용하면 직관적으로 조작할 수 있어 좋습니다.

Git GUI 작업 예


아래의 예에서 파일'풀무.md'중 두 군데가 변경되었고 그 위의 부분만 단계를 진행했다.
  • 스테이지를 원하는 파일을 선택하고 오른쪽 창의 변경 사항을 선택하고 우클릭

  • "Stage Hunk For Commit"를 선택하거나 그림의 예에서 보듯이 변경된 행을 선택한 상태에서 "Stage Lines For Commit"를 선택합니다.


  • 다음 예제에서 보듯이 선택 영역은 색인에만 추가하고 선택하지 않은 영역은 Unstage Changes에 유지합니다.

  • 문제


    Git의 일본어 문제는 많이 완화되었지만 Git for Windows에는 문제가 있습니다.
    작업 대상의 파일에 다자간 문자를 포함하면 이 기능은 실패합니다.실제로 위의 예는 처리하지 않으면 다음과 같이 실패한다.메시지 속의 파일 이름이 물통이라는 것을 안다.

    실패 예



    대상 버전


    Git for Windows 버전 2.18.0에서 확인
    $ git --version
    git version 2.18.0.windows.1
    

    처리하다


    다음 두 가지 패치를 고려했습니다.이 중 하나"C:\Program Files (x86)\Git\mingw64\share\git-gui\lib\diff.tcl"이 파일에 적용하면 문제를 해결할 수 있다.

    패치 1

    --- diff.tcl.orig   2018-06-22 11:12:04.000000000 +0900
    +++ diff.tcl    2018-07-18 22:49:38.130462100 +0900
    @@ -603,11 +603,14 @@
            set e_lno end
        }
    
    +   set current_diff_header [replace_diff_header $current_diff_header $current_diff_path]
    +
        if {[catch {
            set enc [get_path_encoding $current_diff_path]
            set p [eval git_write $apply_cmd]
    -       fconfigure $p -translation binary -encoding $enc
    +       fconfigure $p -translation binary -encoding utf-8
            puts -nonewline $p $current_diff_header
    +       fconfigure $p -translation binary -encoding $enc
            puts -nonewline $p [$ui_diff get $s_lno $e_lno]
            close $p} err]} {
            error_popup "$failed_msg\n\n$err"
    @@ -640,6 +643,21 @@
        }
     }
    
    +proc replace_diff_header {diff_header path_name} {
    +
    +    set index_line {}
    +
    +   if {[regexp -line {^(index.*)$} $diff_header - index_line]} {
    +       return "diff --git a/$path_name b/$path_name
    +$index_line
    +--- a/$path_name
    ++++ b/$path_name
    +"
    +   } else {
    +       return $diff_header
    +   }
    +}
    +
     proc apply_range_or_line {x y} {
        global current_diff_path current_diff_header current_diff_side
        global ui_diff ui_index file_states
    @@ -822,11 +840,14 @@
            set first_l [$ui_diff index "$next_l + 1 lines"]
        }
    
    +   set current_diff_header [replace_diff_header $current_diff_header $current_diff_path]
    +
        if {[catch {
            set enc [get_path_encoding $current_diff_path]
            set p [eval git_write $apply_cmd]
    -       fconfigure $p -translation binary -encoding $enc
    +       fconfigure $p -translation binary -encoding utf-8
            puts -nonewline $p $current_diff_header
    +       fconfigure $p -translation binary -encoding $enc
            puts -nonewline $p $wholepatch
            close $p} err]} {
            error_popup "$failed_msg\n\n$err"
    

    패치 2

    --- diff.tcl.orig   2018-06-22 11:12:04.000000000 +0900
    +++ diff.tcl    2018-07-18 22:51:35.600088600 +0900
    @@ -362,9 +362,9 @@
        set ::current_diff_inheader 1
        fconfigure $fd \
            -blocking 0 \
    -       -encoding [get_path_encoding $path] \
    +       -encoding utf-8 \
            -translation lf
    -   fileevent $fd readable [list read_diff $fd $conflict_size $cont_info]
    +   fileevent $fd readable [list read_diff $fd $conflict_size $cont_info [get_path_encoding $path]]
     }
    
     proc parse_color_line {line} {
    @@ -392,7 +392,7 @@
        return [list $result $markup]
     }
    
    -proc read_diff {fd conflict_size cont_info} {
    +proc read_diff {fd conflict_size cont_info diff_enc} {
        global ui_diff diff_active is_submodule_diff
        global is_3way_diff is_conflict_diff current_diff_header
        global current_diff_queue
    @@ -410,11 +410,15 @@
                || [string match {diff --cc *}       $line]
                || [string match {diff --combined *} $line]} {
                set ::current_diff_inheader 1
    +           fconfigure $fd -encoding utf-8
            }
    
            # -- Check for end of diff header (any hunk line will do this).
            #
    -       if {[regexp {^@@+ } $line]} {set ::current_diff_inheader 0}
    +       if {[regexp {^@@+ } $line]} {
    +           set ::current_diff_inheader 0
    +           fconfigure $fd -encoding $diff_enc
    +       }
    
            # -- Automatically detect if this is a 3 way diff.
            #
    @@ -429,6 +433,7 @@
                if {   [string match {Binary files * and * differ} $line]
                    || [regexp {^\* Unmerged path }                $line]} {
                    set ::current_diff_inheader 0
    +               fconfigure $fd -encoding $diff_enc
                } else {
                    append current_diff_header $line "\n"
                }
    @@ -606,8 +611,9 @@
        if {[catch {
            set enc [get_path_encoding $current_diff_path]
            set p [eval git_write $apply_cmd]
    -       fconfigure $p -translation binary -encoding $enc
    +       fconfigure $p -translation binary -encoding utf-8
            puts -nonewline $p $current_diff_header
    +       fconfigure $p -translation binary -encoding $enc
            puts -nonewline $p [$ui_diff get $s_lno $e_lno]
            close $p} err]} {
            error_popup "$failed_msg\n\n$err"
    @@ -825,8 +831,9 @@
        if {[catch {
            set enc [get_path_encoding $current_diff_path]
            set p [eval git_write $apply_cmd]
    -       fconfigure $p -translation binary -encoding $enc
    +       fconfigure $p -translation binary -encoding utf-8
            puts -nonewline $p $current_diff_header
    +       fconfigure $p -translation binary -encoding $enc
            puts -nonewline $p $wholepatch
            close $p} err]} {
            error_popup "$failed_msg\n\n$err"
    

    해설


    Git GUI에서 파일을 인코딩합니다.gitattributes가 지정한 인코딩 파라미터의 값을 디코딩하려고 합니다.이 기본값은 일본판 Windows에서cp932이기 때문에 아무것도 지정하지 않으면 파일의 내용은cp932로 간주됩니다.
    다른 한편,git diff 출력
    diff --git a/パス名 b/パス名
    index xxxx yyyy 06000
    --- a/パス名
    +++ b/パス名
     foo
     bar
    -baz
    +foo
     foo
     bar
    
    이렇게 하면 처음 4행의 제목 부분은 Git for Windows의 Git에서 UTF-8로 출력됩니다.
    그리고 Git GUI가 패치의 내용을 불러올 때 이 diff의 출력에 따라 대상을 결정하는 파일을 시도하지만 UTF-8의 출력을cp932로 간주하여 디코딩을 하기 위해 혼란을 일으킨다.
    처리된 패치 1에서 머리 부분을 직접 다시 만들어서 처리합니다.패치 2에서 diff의 출력을 읽을 때 최초의 네 줄은 UTF-8로 읽고, 나머지는 파일의 인코딩을 통해 읽으며 혼란을 일으키지 않습니다.
    이 분석 결과에 따르면 UTF-8에서 파일을 항상 처리하면 본 보도의 패치가 없어도 정확한 동작을 할 수 있다.그래서
    .gitattributes
    * encoding=utf-8
    
    등등, 만약 파일의 인코딩이 항상 UTF-8이라고 가정하고, 실제 제작된 파일도 UTF-8이라면 패치가 필요하지 않다고 생각한다.하지만 Windows 환경에서 그런 일이 가능합니까?의문입니다.
    또 하나, 나중에야 알아차렸다
    git config core.quotepath true
    
    그래도 문제 없을 거예요.하지만 이렇게 하면git status의 출력이 보기 어려워지기 때문에 Git GUI에 이런 설정을 적용할 수만 있다면 가장 좋을 것이다.

    기타

  • Git GUI에서 일부 패치를 제출하는 기능의 사용 방법과 문제점을 보여줍니다.그러나 현재 유행하는 Visual Studio 코드도 같은 조작을 할 수 있고 일본어와 관련된 문제도 발생하지 않는다.
  • Git GUI의 차분 디스플레이에 사용된 경우git diff -w (공백의 차이는 표시되지 않음) 이 기사에 대응하든 안 하든 패치의 일부분을 무대에 올리는 데 실패합니다.
  • git diff -w 사용할 수 없는 대책으로 Ignore whitespace의 팔꿈치 단추를 추가했다.(이하 git 패치용)
    diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
    index 6de74ce63..3f1300db7 100755
    --- a/git-gui/git-gui.sh
    +++ b/git-gui/git-gui.sh
    @@ -3458,4 +3458,9 @@ trace add variable current_diff_path write trace_current_diff_path
    
     gold_frame .vpane.lower.diff.header
    +set is_ignore_whitespace 0
    +${NS}::checkbutton .vpane.lower.diff.header.chk \
    +   -text [mc "Ignore whitespace"] \
    +   -variable is_ignore_whitespace \
    +   -command reshow_diff
     tlabel .vpane.lower.diff.header.status \
        -background gold \
    @@ -3474,4 +3479,5 @@ tlabel .vpane.lower.diff.header.path \
        -anchor w \
        -justify left
    +pack .vpane.lower.diff.header.chk -side left
     pack .vpane.lower.diff.header.status -side left
     pack .vpane.lower.diff.header.file -side left
    diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
    index 68c4a6c73..d86f1d4c6 100644
    --- a/git-gui/lib/diff.tcl
    +++ b/git-gui/lib/diff.tcl
    @@ -289,4 +289,5 @@ proc start_show_diff {cont_info {add_opts {}}} {
        global ui_diff ui_index ui_workdir
        global current_diff_path current_diff_side current_diff_header
    +   global is_ignore_whitespace
    
        set path $current_diff_path
    @@ -330,4 +331,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
        lappend cmd -p
        lappend cmd --color
    +   if {$is_ignore_whitespace} {
    +       lappend cmd -w
    +   }
        set cmd [concat $cmd $repo_config(gui.diffopts)]
        if {$repo_config(gui.diffcontext) >= 1} {
    

    좋은 웹페이지 즐겨찾기