linux - Commit without add and how to see remote branch log -


1.i'm new git , know happen if i've file modified , staged in past(but modified again), , want commit file using command such :
git commit -m "yada yada" ~/home/dan/project/file_to_commit.py

is equivalent doing:
a.git add ~/home/dan/project/file_to_commit.py
b.git commit -m "yada yada"

if not please explain.

2.how can see remotes branch commits logs?(pushes) without doing git pull?

thanks

this might better 2 separate questions, , second question answered correctly, i'll take stab @ answering both. before start, though, want path ~/home/dan/project/file_to_commit.py pretty suspect: suggests git directory /.git, not idea. i'm going assume, below, .git directory further down , you're adding project/file or file (and i'll trim paths in question).

note tl;dr version of first answer they're almost same, , need know difference in edge cases. (hence the existing answer eleventhend enough purposes.)

q1: add , commit vs git commit path

... i've file modified , staged in past (but modified again), , want commit file using command such as:

git commit -m "yada yada" file_to_commit.py 

is equivalent doing:

git add file_to_commit.py git commit -m "yada yada" 

if not please explain.

no, it's not exactly equivalent. little bit tricky , lot if define terms , few things pinned down bit more.

also, "already staged in past (but modified again)", leaves bit of ambiguity: did git commit in between these operations? i'll address both "yes" , "no" cases describing full, general case.

the index

first, need define git's index or staging area (it has few more names, e.g., cache in git diff --cached, "index" , "staging area" 2 common terms). git has (one, single) standard index—let's call "the" index, , when want refer another, different index, we'll spell out other 1 mean. when run normal git commands, including git add, git updates index.1

next, need take notes on what's in index. aside interesting not relevant here cases merges, , 1 thing i'm leaving out on purpose, in essence, index has 1 entry per file in next commit.2 is, suppose you've made commit, or checked out branch, current commit, in work tree, has 100 files in it. (your work tree may have additional untracked and/or ignored files, long has 100 files.)

using git add

when run git add, git stores new copy of each of files being added repository, calls blob objects. calculates hash value each blob adds repository, puts new hash index.

when run git commit—at least, without either paths or -a—git reads index , uses form new commit. if new commit have same tree previous commit,3 git requires add --allow-empty flag. (this doesn't mean index empty, rather index matches index you'd re-checking-out current commit. --allow-empty might wrong name flag; maybe should have been called --allow-same or allow-unchanged or such.)

hence, if git add path , git commit -m message, you'll commit uses index updated git add, may have additional updates before git add. since there's 1 entry per path, though, if do:

... hack on foo.py ... $ git add foo.py $ echo '# add final comment' >> foo.py $ git add foo.py $ git commit -m 'update foo' 

there 1 update foo.py in new commit.

so what's difference?

i claimed above git commit path (and git commit -a) not exactly same doing git add , git commit. let's @ precise difference.

when give path names (or -a) git commit, git uses new, different, temporary index. starts copying something—exactly gets bit complicated—to temporary index, adds each file committed, makes commit temporary index. once commit done, git goes using normal, ordinary index, , updates index. is, after adding stuff temporary index , committing, also adds regular index.

to see how works need examples. suppose have 2 files , git add change 1 of them:

# assume file1 , file2 in head commit echo add stuff file1 >> file1 git add file1 echo add stuff file2 >> file2 

at point, git status tell have changes file1 staged committed, , changes file2 not staged committed.

if run git add file2; git commit, we'll both updates in new commit. once commit done, git status show there nothing commit. if, instead, do:

git commit -m message file2 

and run git status, we'll see file1 still staged , ready commit. commit made has only change file2.

this because git commit file2 command started making temporary index using head commit, adding file2, making commit, , updating normal index new file2. last bit important: if git didn't copy change (regular) index, index still have old version of file2, , next commit undo change committed.

this copy-back step has important side effect. suppose have complicated change foo.py. instance, suppose went fix bug, , along way refactored few functions. we've tested fix , works, did git add foo.py , commit it:

... hack on foo.py ... ... test, hack more, test, until fixed ... git add foo.py git commit -m 'refactor foo.py , fix bug'^c 

at point realized shouldn't commit both changes together: should commit refactored code first, , then commit bug fix.4

well, we've git add-ed refactored and fixed code, it's safely stashed away in index, right? (no, wrong! danger robinson! let's proceed, since example.) can undo fix part, leaving refactoring, , commit first:

... edit foo.py remove fix ... git commit -m 'refactor code prep bug fix' foo.py 

once commit done, can commit staged version:

git commit -m 'fix bug #12345' foo.py 

alas, git tells there's nothing commit. happened staged full-fix version of foo.py?

the answer is, git commit foo.py wiped out. git first added refactor-only foo.py temporary index , committed that; copied refactor-only foo.py regular index, losing our staged full-fix version. can either re-create it, or fish around in repository "dangling blob" left behind because of this.

(this should considered bug in git, although it's not clear staged uncommitted version.)

git commit -a and/or paths: --only vs --include

here need quote myself moment ago. when using -a or paths, git commit starts copying something—exactly gets bit complicated. if closely @ the git commit documentation, find -i or --include option (and corresponding, default, -o / --only option). these control goes temporary index.

when using --include, git commit creates temporary index current index. when using default --only mode, git commit creates temporary index head commit.

(because of copy-back step @ end, way see both commands in fact using temporary index view index in middle of commit operation. if use --include , check after commit done, regular index match new head commit, if git commit adding regular index rather temporary index. fortunately it's easy view regular index "in middle", not supplying -m flag, git commit fires editor. while that's going on, run git status in window, or using job control. here's example:

# @ point i've modified both a.py , mxgroup.py # have not `git add`ed either one.  $ git add a.py $ git status --short m  a.py  m mxgroup.py  # see plain "git commit" commit a.py, # not mxgroup.py.  $ git commit -i mxgroup.py # waiting in editor  # now, in window: $ git status -s m  a.py  m mxgroup.py 

this shows (regular) index still set way had it. once write message out , exit editor, commit process update regular index new mxgroup.py entry, , now-committed a.py change in new head commit, git status show neither file.)

q2: viewing logs

how can see remotes branch commits logs?(pushes) without doing git pull?

git operates entirely locally. may able directly web viewers, it's pretty convenient locally, first running git fetch.

the git pull command meant convenience. there 2 steps needed incorporate other people's commits:

  1. obtain commits have them locally; and
  2. merge or rebase using commits.

these 2 steps handled different git commands: git fetch step 1, , git merge , git rebase—you must pick 1 of two—does whichever version of step 2 want.

the git pull command step 1, step 2. chooses merge unless instruct otherwise. historical reasons, has multiple ways of choosing operation run in step 2.

my recommendation newbie git, avoid git pull entirely. there 2 reasons this, 1 of valid today (unless you're stuck old versions of git):

  1. traditionally, git pull has had various bugs, of can lose work. (as far know these fixed since git 2.0.)

  2. while is convenient, git pull obscures what's happening , makes choose merge-vs-rebase early. true rebase right answer, git pull defaults doing merge, means default wrong new users. plus, of course, there's "obscures what's happening" issue. if knew fetch , rebase separate steps, question not have come up.


1the index file, , can find in .git/index. can make git use different index setting git_index_file in environment, meant use scripts git stash.

2the cases i'm leaving out are:

  • conflicted merges, record 3 entries per path, using non-zero stage numbers. once resolve conflict , git add result, nonzero stages cleaned out , normal stage-0 result stored instead, , we're normal, ready-to-commit case index intry.

  • removing file in current commit (git rm, or without --cached). writes special stage-0 entry marking file to-be-omitted, rather removing entry.

3if you're committing merge, git allows tree match of or parents, since merge commit needs record multiple parents. "empty" test applied non-merge, single-parent commits. documented better in modern git in old versions of git, still has wrong name.

4this has nothing git itself. idea here commit small, readable, understandable, , importantly testable changes. time find writing commit "do , b, , fix c, , add d , e" it's indication should split 1 commit per thing—in case, 5 separate commits.


Comments