diff --git a/Documentation/RelNotes-1.5.2.4.txt b/Documentation/RelNotes-1.5.2.4.txt new file mode 100644 index 0000000000..75cff475f6 --- /dev/null +++ b/Documentation/RelNotes-1.5.2.4.txt @@ -0,0 +1,28 @@ +GIT v1.5.2.4 Release Notes +========================== + +Fixes since v1.5.2.3 +-------------------- + + * Bugfixes + + - "git-gui" bugfixes, including a handful fixes to run it + better on Cygwin/MSYS. + + - "git checkout" failed to switch back and forth between + branches, one of which has "frotz -> xyzzy" symlink and + file "xyzzy/filfre", while the other one has a file + "frotz/filfre". + + - "git prune" used to segfault upon seeing a commit that is + referred to by a tree object (aka "subproject"). + + - "git diff --name-status --no-index" mishandled an added file. + + - "git apply --reverse --whitespace=warn" still complained + about whitespaces that a forward application would have + introduced. + + * Documentation Fixes and Updates + + - A handful documentation updates. diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 8d06775a6b..87e70fe12d 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -481,8 +481,9 @@ It is recommended that `` always be encoded using UTF-8. `filedelete` ^^^^^^^^^^^^ -Included in a `commit` command to remove a file from the branch. -If the file removal makes its directory empty, the directory will +Included in a `commit` command to remove a file or recursively +delete an entire directory from the branch. If the file or directory +removal makes its parent directory empty, the parent directory will be automatically removed too. This cascades up the tree until the first non-empty directory or the root is reached. @@ -490,7 +491,8 @@ first non-empty directory or the root is reached. 'D' SP LF .... -here `` is the complete path of the file to be removed. +here `` is the complete path of the file or subdirectory to +be removed from the branch. See `filemodify` above for a detailed description of ``. `filedeleteall` diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index a33d157b97..0ca58a7eb3 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -50,6 +50,9 @@ OPTIONS ------- include::diff-options.txt[] +-:: + Limits the number of patches to prepare. + -o|--output-directory :: Use to store the resulting files, instead of the current working directory. diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index e903abfeb8..3f7b1e42b5 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -330,6 +330,12 @@ This commit is referred to as a "merge commit", or sometimes just a denotes a particular <>. These may be stored in `$GIT_DIR/refs/`. +[[def_reflog]]reflog:: + A reflog shows the local "history" of a ref. In other words, + it can tell you what the 3rd last revision in _this_ repository + was, and what was the current state in _this_ repository, + yesterday 9:14pm. See gitlink:git-reflog[1] for details. + [[def_refspec]]refspec:: A "refspec" is used by <> and <> to describe the mapping between remote diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 118ff72869..965ec00a6b 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -304,7 +304,7 @@ it easier: $ git remote add bob /home/bob/myrepo ------------------------------------------------ -With this, you can perform the first operation alone using the +With this, Alice can perform the first operation alone using the "git fetch" command without merging them with her own branch, using: diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 714e6a9942..d6caff4248 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -890,7 +890,7 @@ $ git archive --format=tar --prefix=project/ HEAD | gzip >latest.tar.gz ------------------------------------------------- will use HEAD to produce a tar archive in which each filename is -preceded by "prefix/". +preceded by "project/". If you're releasing a new version of a software project, you may want to simultaneously make a changelog to include in the release @@ -1528,9 +1528,9 @@ dangling tree b24c2473f1fd3d91352a624795be026d64c8841f ------------------------------------------------- Dangling objects are not a problem. At worst they may take up a little -extra disk space. They can sometimes provide a last-resort method of -recovery lost work--see <> for details. However, if -you want, you may remove them with gitlink:git-prune[1] or the --prune +extra disk space. They can sometimes provide a last-resort method for +recovering lost work--see <> for details. However, if +you wish, you can remove them with gitlink:git-prune[1] or the --prune option to gitlink:git-gc[1]: ------------------------------------------------- @@ -1772,7 +1772,7 @@ repository, but it works just as well in the other direction. If you and the maintainer both have accounts on the same machine, then you can just pull changes from each other's repositories directly; -commands that accepts repository URLs as arguments will also accept a +commands that accept repository URLs as arguments will also accept a local directory name: ------------------------------------------------- @@ -1780,6 +1780,15 @@ $ git clone /path/to/repository $ git pull /path/to/other/repository ------------------------------------------------- +or an ssh url: + +------------------------------------------------- +$ git clone ssh://yourhost/~you/repository +------------------------------------------------- + +For projects with few developers, or for synchronizing a few private +repositories, this may be all you need. + However, the more common way to do this is to maintain a separate public repository (usually on a different host) for others to pull changes from. This is usually more convenient, and allows you to cleanly @@ -1802,6 +1811,8 @@ like this: | they push V their public repo <------------------- their repo +We explain how to do this in the following sections. + [[setting-up-a-public-repository]] Setting up a public repository ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1913,6 +1924,12 @@ proceeding the branch name by a plus sign: $ git push ssh://yourserver.com/~you/proj.git +master ------------------------------------------------- +Note that the target of a "push" is normally a +<> repository. You can also push to a +repository that has a checked-out working tree, but the working tree +will not be updated by the push. This may lead to unexpected results if +the branch you push to is the currently checked-out branch! + As with git-fetch, you may also set up configuration options to save typing; so, for example, after diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 5c6d2b2898..a318baa798 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.2.3.GIT +DEF_VER=v1.5.2.4.GIT LF=' ' diff --git a/RelNotes b/RelNotes index a1c82a863b..1f6c16e1dc 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes-1.5.2.3.txt \ No newline at end of file +Documentation/RelNotes-1.5.2.4.txt \ No newline at end of file diff --git a/builtin-apply.c b/builtin-apply.c index 0399743c4e..490e23ef40 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1003,12 +1003,16 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s trailing++; break; case '-': + if (apply_in_reverse && + new_whitespace != nowarn_whitespace) + check_whitespace(line, len); deleted++; oldlines--; trailing = 0; break; case '+': - if (new_whitespace != nowarn_whitespace) + if (!apply_in_reverse && + new_whitespace != nowarn_whitespace) check_whitespace(line, len); added++; newlines--; diff --git a/diff.c b/diff.c index 07b326638c..3b1ac58e6e 100644 --- a/diff.c +++ b/diff.c @@ -2402,7 +2402,8 @@ static void diff_flush_raw(struct diff_filepair *p, printf("%s ", diff_unique_abbrev(p->two->sha1, abbrev)); } - printf("%s%c%s", status, inter_name_termination, path_one); + printf("%s%c%s", status, inter_name_termination, + two_paths || p->one->mode ? path_one : path_two); if (two_paths) printf("%c%s", inter_name_termination, path_two); putchar(line_termination); diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index 4fbc408c4d..c38aa067ac 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -1042,15 +1042,17 @@ proc do_gitk {revs} { # lets us bypass using shell process on Windows systems. # set cmd [list [info nameofexecutable]] - lappend cmd [gitexec gitk] + set exe [gitexec gitk] + lappend cmd $exe if {$revs ne {}} { append cmd { } append cmd $revs } - if {[catch {eval exec $cmd &} err]} { - error_popup "Failed to start gitk:\n\n$err" + if {! [file exists $exe]} { + error_popup "Unable to start gitk:\n\n$exe does not exist" } else { + eval exec $cmd & set ui_status_value $starting_gitk_msg after 10000 { if {$ui_status_value eq $starting_gitk_msg} { @@ -1523,7 +1525,8 @@ if {[is_enabled transport]} { menu .mbar.push .mbar.push add command -label {Push...} \ - -command do_push_anywhere + -command do_push_anywhere \ + -accelerator $M1T-P } if {[is_MacOSX]} { @@ -1819,6 +1822,10 @@ pack .vpane.lower.commarea.buttons.commit -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.commit conf -state} +button .vpane.lower.commarea.buttons.push -text {Push} \ + -command do_push_anywhere +pack .vpane.lower.commarea.buttons.push -side top -fill x + # -- Commit Message Buffer # frame .vpane.lower.commarea.buffer @@ -2146,10 +2153,14 @@ if {[is_enabled branch]} { bind . <$M1B-Key-n> do_create_branch bind . <$M1B-Key-N> do_create_branch } +if {[is_enabled transport]} { + bind . <$M1B-Key-p> do_push_anywhere + bind . <$M1B-Key-P> do_push_anywhere +} -bind all do_rescan -bind all <$M1B-Key-r> do_rescan -bind all <$M1B-Key-R> do_rescan +bind . do_rescan +bind . <$M1B-Key-r> do_rescan +bind . <$M1B-Key-R> do_rescan bind . <$M1B-Key-s> do_signoff bind . <$M1B-Key-S> do_signoff bind . <$M1B-Key-i> do_add_all diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl index b523654815..1d2caac283 100644 --- a/git-gui/lib/blame.tcl +++ b/git-gui/lib/blame.tcl @@ -547,6 +547,10 @@ method _read_blame {fd cur_w cur_d cur_s} { set a_name {} catch {set a_name $header($cmit,author)} while {$a_name ne {}} { + if {$author_abbr ne {} + && [string index $a_name 0] eq {'}} { + regsub {^'[^']+'\s+} $a_name {} a_name + } if {![regexp {^([[:upper:]])} $a_name _a]} break append author_abbr $_a unset _a diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl index 3d6341bcc5..e612247c9e 100644 --- a/git-gui/lib/browser.tcl +++ b/git-gui/lib/browser.tcl @@ -11,6 +11,8 @@ field browser_status {Starting...} field browser_stack {} field browser_busy 1 +field ls_buf {}; # Buffered record output from ls-tree + constructor new {commit} { global cursor_ptr M1B make_toplevel top w @@ -160,7 +162,7 @@ method _click {was_double_click pos} { } method _ls {tree_id {name {}}} { - set browser_buffer {} + set ls_buf {} set browser_files {} set browser_busy 1 @@ -185,17 +187,19 @@ method _ls {tree_id {name {}}} { } method _read {fd} { - append browser_buffer [read $fd] - set pck [split $browser_buffer "\0"] - set browser_buffer [lindex $pck end] + append ls_buf [read $fd] + set pck [split $ls_buf "\0"] + set ls_buf [lindex $pck end] set n [llength $browser_files] $w conf -state normal foreach p [lrange $pck 0 end-1] { - set info [split $p "\t"] - set path [lindex $info 1] - set info [split [lindex $info 0] { }] - set type [lindex $info 1] + set tab [string first "\t" $p] + if {$tab == -1} continue + + set info [split [string range $p 0 [expr {$tab - 1}]] { }] + set path [string range $p [expr {$tab + 1}] end] + set type [lindex $info 1] set object [lindex $info 2] switch -- $type { @@ -225,7 +229,7 @@ method _read {fd} { close $fd set browser_status Ready. set browser_busy 0 - unset browser_buffer + set ls_buf {} if {$n > 0} { $w tag add in_sel 1.0 2.0 focus -force $w diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl index 9af9b4e426..e139f4da2b 100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@ -257,6 +257,34 @@ proc commit_committree {fd_wt curHEAD msg} { return } + # -- Verify this wasn't an empty change. + # + if {$commit_type eq {normal}} { + set fd_ot [open "| git cat-file commit $PARENT" r] + fconfigure $fd_ot -encoding binary -translation lf + set old_tree [gets $fd_ot] + close $fd_ot + + if {[string equal -length 5 {tree } $old_tree] + && [string length $old_tree] == 45} { + set old_tree [string range $old_tree 5 end] + } else { + error "Commit $PARENT appears to be corrupt" + } + + if {$tree_id eq $old_tree} { + info_popup {No changes to commit. + +No files were modified by this commit and it was not a merge commit. + +A rescan will be automatically started now. +} + unlock_index + rescan {set ui_status_value {No changes to commit.}} + return + } + } + # -- Build the message. # set msg_p [gitdir COMMIT_EDITMSG] diff --git a/git-gui/lib/console.tcl b/git-gui/lib/console.tcl index ce25d92cac..34de5d4859 100644 --- a/git-gui/lib/console.tcl +++ b/git-gui/lib/console.tcl @@ -31,16 +31,20 @@ method _init {} { -background white -borderwidth 1 \ -relief sunken \ -width 80 -height 10 \ + -wrap none \ -font font_diff \ -state disabled \ + -xscrollcommand [list $w.m.sbx set] \ -yscrollcommand [list $w.m.sby set] label $w.m.s -text {Working... please wait...} \ -anchor w \ -justify left \ -font font_uibold + scrollbar $w.m.sbx -command [list $w.m.t xview] -orient h scrollbar $w.m.sby -command [list $w.m.t yview] pack $w.m.l1 -side top -fill x pack $w.m.s -side bottom -fill x + pack $w.m.sbx -side bottom -fill x pack $w.m.sby -side right -fill y pack $w.m.t -side left -fill both -expand 1 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10 diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl index ae0389df5b..889182f545 100644 --- a/git-gui/lib/merge.tcl +++ b/git-gui/lib/merge.tcl @@ -213,7 +213,9 @@ proc dialog {} { pack $w.buttons.visualize -side left button $w.buttons.create -text Merge -command $_start pack $w.buttons.create -side right - button $w.buttons.cancel -text {Cancel} -command [list destroy $w] + button $w.buttons.cancel \ + -text {Cancel} \ + -command "unlock_index;destroy $w" pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl index ebf72e4452..a0a1b7dddd 100644 --- a/git-gui/lib/shortcut.tcl +++ b/git-gui/lib/shortcut.tcl @@ -9,6 +9,9 @@ proc do_windows_shortcut {} { -title "[appname] ([reponame]): Create Desktop Icon" \ -initialfile "Git [reponame].bat"] if {$fn != {}} { + if {[file extension $fn] ne {.bat}} { + set fn ${fn}.bat + } if {[catch { set fd [open $fn w] puts $fd "@ECHO Entering [reponame]" @@ -42,6 +45,9 @@ proc do_cygwin_shortcut {} { -initialdir $desktop \ -initialfile "Git [reponame].bat"] if {$fn != {}} { + if {[file extension $fn] ne {.bat}} { + set fn ${fn}.bat + } if {[catch { set fd [open $fn w] set sh [exec cygpath \ diff --git a/sha1_file.c b/sha1_file.c index 5453bc3e36..e69b17ddb2 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -360,10 +360,14 @@ static void read_info_alternates(const char * relative_base, int depth) char *map; size_t mapsz; struct stat st; - char path[PATH_MAX]; + const char alt_file_name[] = "info/alternates"; + /* Given that relative_base is no longer than PATH_MAX, + ensure that "path" has enough space to append "/", the + file name, "info/alternates", and a trailing NUL. */ + char path[PATH_MAX + 1 + sizeof alt_file_name]; int fd; - sprintf(path, "%s/info/alternates", relative_base); + sprintf(path, "%s/%s", relative_base, alt_file_name); fd = open(path, O_RDONLY); if (fd < 0) return; @@ -824,7 +828,10 @@ void install_packed_git(struct packed_git *pack) static void prepare_packed_git_one(char *objdir, int local) { - char path[PATH_MAX]; + /* Ensure that this buffer is large enough so that we can + append "/pack/" without clobbering the stack even if + strlen(objdir) were PATH_MAX. */ + char path[PATH_MAX + 1 + 4 + 1 + 1]; int len; DIR *dir; struct dirent *de; @@ -846,6 +853,9 @@ static void prepare_packed_git_one(char *objdir, int local) if (!has_extension(de->d_name, ".idx")) continue; + if (len + namelen + 1 > sizeof(path)) + continue; + /* Don't reopen a pack we already have. */ strcpy(path + len, de->d_name); for (p = packed_git; p; p = p->next) { diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh new file mode 100755 index 0000000000..0526fce163 --- /dev/null +++ b/t/t2007-checkout-symlink.sh @@ -0,0 +1,50 @@ +#!/bin/sh +# +# Copyright (c) 2007 Junio C Hamano + +test_description='git checkout to switch between branches with symlink<->dir' + +. ./test-lib.sh + +test_expect_success setup ' + + mkdir frotz && + echo hello >frotz/filfre && + git add frotz/filfre && + test_tick && + git commit -m "master has file frotz/filfre" && + + git branch side && + + echo goodbye >nitfol && + git add nitfol + test_tick && + git commit -m "master adds file nitfol" && + + git checkout side && + + git rm --cached frotz/filfre && + mv frotz xyzzy && + ln -s xyzzy frotz && + git add xyzzy/filfre frotz && + test_tick && + git commit -m "side moves frotz/ to xyzzy/ and adds frotz->xyzzy/" + +' + +test_expect_success 'switch from symlink to dir' ' + + git checkout master + +' + +rm -fr frotz xyzzy nitfol && +git checkout -f master || exit + +test_expect_success 'switch from dir to symlink' ' + + git checkout side + +' + +test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 8f4c29a6b5..4e7d68dda2 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -17,6 +17,7 @@ test_expect_success setup ' export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && mkdir dir && + mkdir dir2 && for i in 1 2 3; do echo $i; done >file0 && for i in A B; do echo $i; done >dir/sub && cat file0 >file2 && @@ -252,6 +253,7 @@ diff --patch-with-stat initial..side diff --patch-with-raw initial..side diff --patch-with-stat -r initial..side diff --patch-with-raw -r initial..side +diff --name-status dir2 dir EOF test_done diff --git a/t/t4013/diff.diff_--name-status_dir2_dir b/t/t4013/diff.diff_--name-status_dir2_dir new file mode 100644 index 0000000000..ef7fdb7335 --- /dev/null +++ b/t/t4013/diff.diff_--name-status_dir2_dir @@ -0,0 +1,3 @@ +$ git diff --name-status dir2 dir +A dir/sub +$ diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh index 2685b22630..11e02807a5 100755 --- a/t/t4116-apply-reverse.sh +++ b/t/t4116-apply-reverse.sh @@ -82,4 +82,10 @@ test_expect_success 'apply in reverse without postimage' ' ) ' +test_expect_success 'reversing a whitespace introduction' ' + sed "s/a/a /" < file1 > file1.new && + mv file1.new file1 && + git diff | git apply --reverse --whitespace=error +' + test_done diff --git a/unpack-trees.c b/unpack-trees.c index cac2411b9d..89dd279f89 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -495,6 +495,9 @@ static void verify_absent(const char *path, const char *action, if (o->index_only || o->reset || !o->update) return; + if (has_symlink_leading_path(path, NULL)) + return; + if (!lstat(path, &st)) { int cnt;