Git GUI에서 패치 일부를 제출하는 일본어 기능 지원
패치 제출 기능
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 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에 이런 설정을 적용할 수만 있다면 가장 좋을 것이다.
기타
--- 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"
--- 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 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} {
Reference
이 문제에 관하여(Git GUI에서 패치 일부를 제출하는 일본어 기능 지원), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/jca02266/items/f127188a543973522695텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)